Landing page v2 + CodeRabbit fixes#2
Conversation
Replaces the AI-slop landing page with a redesign anchored in actual
product capabilities. The previous hero used a fake "Try It" demo input
that did nothing (the app requires login to shorten links), and the
features section was a generic 3-col emoji grid that didn't reflect the
real surface area of the product.
Changes:
- LandingPage.jsx — full rewrite with five new sections:
* Hero with realistic LinkCardMockup mirroring the dashboard's
LinkRow (animated counter, sparkline, feature pills, top
countries) instead of a fake input
* Anatomy of a Link — 8-cell grid of every per-link config option
(slug, password, click limit, expiry, iOS/Android routing, OG
metadata, QR), pulled from the actual EditModal fields
* Analytics showcase — hourly chart, device breakdown, UTM source
bars, bot detection counter; matches AnalyticsPanel's real surfaces
* Self-host — three numbered steps with real shell commands
(gh repo fork, wrangler kv namespace create KV, wrangler deploy)
* Clean two-col CTA replacing the giant centered gradient block
- Framer Motion entrance + scroll-triggered animations replace the
old CSS keyframe stagger
- Hero H1 reduced to clamp(2.4rem, 3.6vw, 3.6rem) with display:block
span so the gradient phrase sits cleanly on its own line
- Ticker dot spacing fixed to 24px on both sides (was 16/48 lopsided)
- AuthCard.jsx — redesigned to match landing aesthetic with eyebrow
label, ambient glow, deeper glassmorphism, Framer Motion entrance
- Login.jsx / Signup.jsx — eyebrow labels, btn-p shimmer button,
refined divider copy ("OR EMAIL")
- App.jsx — added .hero-grid, .feat-row-grid, .analytics-wide,
.analytics-narrow, .self-host-grid responsive rules
- frontend/package.json — adds framer-motion@^12
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- AuthCard: forward props.onFocus/onBlur so consumer handlers still fire - AuthCard: make password toggle keyboard-accessible (remove tabIndex=-1, add aria-pressed) - LandingPage: guard Sparkline against NaN on single-data-point arrays - LandingPage: add anatomy-grid className for mobile single-column layout - App: add @media(max-width:600px) anatomy-grid responsive rule - Login/Signup: wrap r.json() in try/catch to handle non-JSON error responses Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR redesigns the landing page with Framer Motion: adds the framer-motion dependency, introduces animated primitives (HeroGlow, Sparkline, Counter, SectionHeading), builds a new hero LinkCardMockup and multiple content sections, updates AuthCard (eyebrow + entrance animation), changes Login/Signup to safely parse non-JSON responses and updates their UI, and adds responsive CSS for the layout. ChangesLanding Page & Animation Redesign
🎯 4 (Complex) | ⏱️ ~45 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
frontend/src/pages/Login.jsx (1)
9-9: 💤 Low valueUnused
toastprop.The
toastprop is received but never used in this component. Consider removing it if not needed, or using it for success/error notifications instead of (or in addition to) the inline error state.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/pages/Login.jsx` at line 9, The LoginPage component declares a toast prop but never uses it; either remove toast from the LoginPage signature and any prop types/consumers that pass it, or wire it into the existing error/success handling (replace or augment the local error state usage) by calling toast.error(...) and toast.success(...) where the component currently sets error messages or handles successful login. Update the LoginPage function signature and any places that import/instantiate it (or add toast calls in the submit/login handlers that set the local error) so the prop is either used or eliminated.frontend/src/pages/LandingPage.jsx (1)
62-67: 💤 Low valueMissing dependencies in useEffect.
The dependency array
[inView, to]is missingdurationandformat. While these props are unlikely to change at runtime, adding them would silence React's exhaustive-deps lint warning and prevent potential stale closure issues.Proposed fix
useEffect(() => { if (!inView) return; const controls = animate(count, to, { duration, ease: EASE }); const unsub = rounded.on('change', (v) => setDisplay(v)); return () => { controls.stop(); unsub(); }; - }, [inView, to]); + }, [inView, to, duration, format, count, rounded]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/pages/LandingPage.jsx` around lines 62 - 67, The useEffect that starts the animation with animate(count, to, { duration, ease: EASE }) and subscribes to rounded.on('change', v => setDisplay(v)) is missing dependencies; include duration and format in the dependency array so the effect re-runs if those props change and to silence exhaustive-deps lint warnings—update the dependency array for the useEffect containing animate, count, to, duration, EASE, rounded, setDisplay, and format accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@frontend/src/pages/LandingPage.jsx`:
- Around line 62-67: The useEffect that starts the animation with animate(count,
to, { duration, ease: EASE }) and subscribes to rounded.on('change', v =>
setDisplay(v)) is missing dependencies; include duration and format in the
dependency array so the effect re-runs if those props change and to silence
exhaustive-deps lint warnings—update the dependency array for the useEffect
containing animate, count, to, duration, EASE, rounded, setDisplay, and format
accordingly.
In `@frontend/src/pages/Login.jsx`:
- Line 9: The LoginPage component declares a toast prop but never uses it;
either remove toast from the LoginPage signature and any prop types/consumers
that pass it, or wire it into the existing error/success handling (replace or
augment the local error state usage) by calling toast.error(...) and
toast.success(...) where the component currently sets error messages or handles
successful login. Update the LoginPage function signature and any places that
import/instantiate it (or add toast calls in the submit/login handlers that set
the local error) so the prop is either used or eliminated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 5020cfe2-5e5a-4f62-a20e-1a64cfcaaebb
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
frontend/package.jsonfrontend/src/App.jsxfrontend/src/components/AuthCard.jsxfrontend/src/pages/LandingPage.jsxfrontend/src/pages/Login.jsxfrontend/src/pages/Signup.jsx
- Counter useEffect: add duration, format, count, rounded to deps array - LoginPage/SignupPage: remove unused toast prop from function signatures Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/pages/Login.jsx`:
- Around line 29-32: The response handling doesn't validate that a successful
HTTP response actually contains the expected token and user, so when d is {} (or
partial) you may call login with invalid data; update the success branch that
currently calls login(d.token, d.user) and navigate(from, ...) to first check
that d && typeof d.token === 'string' && d.token.length > 0 && d.user (or more
specific shape you expect) and call setError('Login failed.') and return if
those fields are missing; modify the block around the r.json fallback (variable
d), the r.ok check, and the call sites login(...) and navigate(...) to enforce
this guard before creating a session.
In `@frontend/src/pages/Signup.jsx`:
- Around line 30-33: The success path calls login(d.token, d.user) without
validating the parsed payload, which can be undefined if JSON parsing failed or
the backend returned incomplete data; update the Signup.jsx flow after parsing
(variables r and d) to check that d is an object and contains both d.token and
d.user before calling login, and if either is missing call setError('Signup
failed.') (or a clearer message) and return instead of calling navigate; ensure
the try/catch leaves d in a known state (null/undefined) that your guard
accounts for so you never pass undefined to login.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2ea7f457-9abc-4caa-9f8c-dc8220098ad1
📒 Files selected for processing (3)
frontend/src/pages/LandingPage.jsxfrontend/src/pages/Login.jsxfrontend/src/pages/Signup.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/pages/LandingPage.jsx
Prevent calling login() with undefined values when the server returns a 200 with an unexpected or empty payload. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
frontend/src/pages/Login.jsx (1)
42-52: ⚡ Quick winUnify and validate OAuth success payload before
login(...).The three
onSuccesshandlers duplicate logic and currently trust callback shape. A shared guarded handler avoids drift and blocks invalid session writes if a provider returns partial data.Proposed refactor
+ const handleOAuthSuccess = ({ token, user }) => { + if (!token || !user) { + setError('Unexpected server response. Please try again.'); + return; + } + login(token, user); + navigate(from, { replace: true }); + }; <div style={{ display: 'flex', gap: 10, marginBottom: 10 }}> <GitHubSignInButton - onSuccess={({ token, user }) => { login(token, user); navigate(from, { replace: true }); }} + onSuccess={handleOAuthSuccess} onError={msg => setError(msg)} /> <DiscordSignInButton - onSuccess={({ token, user }) => { login(token, user); navigate(from, { replace: true }); }} + onSuccess={handleOAuthSuccess} onError={msg => setError(msg)} /> </div> <GoogleSignInButton - onSuccess={({ token, user }) => { login(token, user); navigate(from, { replace: true }); }} + onSuccess={handleOAuthSuccess} onError={msg => setError(msg)} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/pages/Login.jsx` around lines 42 - 52, Centralize and validate the OAuth success payload instead of duplicating inline handlers: create a single guarded handler (e.g., handleOAuthSuccess) that accepts the provider payload, checks that both token and user exist and are of expected shape, calls login(token, user) and then navigate(from, { replace: true }) only when valid, and calls setError(...) with a clear message when missing/invalid; replace each component's onSuccess (DiscordSignInButton, GoogleSignInButton, and the other provider's onSuccess) to use this shared handleOAuthSuccess and keep onError={msg => setError(msg)} as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/pages/Login.jsx`:
- Line 62: The login error div in Login.jsx (the JSX that renders {error}) is
not announced to screen readers; update that element (the div that displays the
error message for the error variable) to be a live region by adding role="alert"
or aria-live="assertive" (and keep existing styling props) so assistive
technology announces login failures immediately; ensure the change is applied to
the same JSX element that renders {error} in the Login component.
---
Nitpick comments:
In `@frontend/src/pages/Login.jsx`:
- Around line 42-52: Centralize and validate the OAuth success payload instead
of duplicating inline handlers: create a single guarded handler (e.g.,
handleOAuthSuccess) that accepts the provider payload, checks that both token
and user exist and are of expected shape, calls login(token, user) and then
navigate(from, { replace: true }) only when valid, and calls setError(...) with
a clear message when missing/invalid; replace each component's onSuccess
(DiscordSignInButton, GoogleSignInButton, and the other provider's onSuccess) to
use this shared handleOAuthSuccess and keep onError={msg => setError(msg)}
as-is.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f31df791-efa3-425c-9638-dce0b186c329
📒 Files selected for processing (2)
frontend/src/pages/Login.jsxfrontend/src/pages/Signup.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/pages/Signup.jsx
- Add role="alert" aria-live="assertive" to error divs (Login + Signup) - Extract shared handleOAuthSuccess with token/user guard (Login + Signup) replaces three duplicated inline onSuccess handlers per page Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
CodeRabbit fixes
AuthCard.jsx: forwardprops.onFocus/props.onBlurso consumer handlers fire through the styled focus/blurAuthCard.jsx: password visibility toggle is now keyboard-reachable (removedtabIndex={-1}, addedaria-pressed)LandingPage.jsx: Sparkline guards againstNaNcoordinates on single-element data arrays (Math.max(data.length - 1, 1))LandingPage.jsx+App.jsx: anatomy grid gets.anatomy-gridclass with@media(max-width:600px)single-column overrideLogin.jsx/Signup.jsx:r.json()wrapped intry/catch— non-JSON or empty error responses no longer throw and mask the real error messageTest plan
aria-pressedupdates on toggle🤖 Generated with Claude Code
Summary by CodeRabbit