Session 34: Design system Phase C — app shell, nav, routing, auth gate, footer, 404 (1818 tests)
VYNDR 2.0 conversion, Phase C (the frame every page sits inside). Frontend-only; zero backend changes. - Nav rewritten: new .wm Wordmark, mono uppercase links, More dropdown, search/ bell/read-meter/avatar, Ticker under the bar. layout main paddingTop 64 -> 96. - Routing: web/src/lib/routes.js (GATED/OPEN/HASH_ALIASES, isGatedRoute, resolveHashAlias). Client AuthGate bounces signed-out users off personal routes to /login?next=. HashRedirect maps #scan/#terminal to real routes. - Footer rewritten to system voice + Detroit signature; mounted globally in layout (removed per-page dup). - 404 converted to the north star (scanlines, crt-sweep, glitch wordmark, amber). - Stub pages for terminal/compare/invite/help/about/notifications via RouteStub. Honest reconciliations: auth gate is client-side (no auth-helpers pkg; session is client-side Supabase); GATED narrowed to protect the free-scan funnel; did not stub over existing real pages; redirect param is ?next= (what /login reads). 26 new tests. Backend 1792 -> 1818, 142 suites, zero regressions. Web build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -165,6 +165,38 @@ Multi-session frontend conversion of the claude.ai/design "VYNDR 2.0" handoff
|
||||
data-motion>` overrides in globals.css. Wiring the toggles to these attrs is
|
||||
Phase G (Session 38).
|
||||
|
||||
## VYNDR 2.0 App Shell (Session 34 — Phase C)
|
||||
The frame every page sits in. Frontend-only.
|
||||
- **Routing config** = `web/src/lib/routes.js` (CommonJS so it's unit-testable):
|
||||
`GATED_ROUTES`, `OPEN_ROUTES`, `HASH_ALIASES`, `isGatedRoute()`,
|
||||
`resolveHashAlias()`. GATED is deliberately narrow — only personal surfaces
|
||||
(ledger/tracker/account/profile/settings/notifications/invite). dashboard +
|
||||
scan stay OPEN (the free-scan funnel); gating them would be a monetization
|
||||
regression.
|
||||
- **Auth gate = CLIENT-side** (`components/AuthGate.tsx`, mounted around `<main>`
|
||||
in layout). Our Supabase session lives in localStorage, not an httpOnly cookie,
|
||||
and `middleware.ts` is locale-only — a server middleware can't read it. The
|
||||
gate uses `useAuth().loading/user` + `isGatedRoute()` and redirects to
|
||||
`/login?next=<path>` (the param `/login` already consumes). Do NOT try to move
|
||||
this to middleware without first adding `@supabase/auth-helpers-nextjs` +
|
||||
cookie sessions (a separate, larger change).
|
||||
- **Hash deep-links**: `components/vyndr/HashRedirect.tsx` translates
|
||||
`#scan`/`#terminal`/… → real Next routes once on mount. We keep file-based
|
||||
routing; hashes are just redirect aliases for old share links / PWA shortcuts.
|
||||
- **Nav** (`components/Nav.tsx`): uses the new `@/components/vyndr` Wordmark
|
||||
(`.wm`), mono uppercase links, active = `--g-a`, a More dropdown, and a
|
||||
**Ticker** under the bar. The fixed header is 60px nav + 32px ticker, so layout
|
||||
`main` paddingTop is **96** (not 64) — keep that in sync if the header height
|
||||
changes.
|
||||
- **Footer** (`components/Footer.tsx`) is mounted GLOBALLY in the layout (not
|
||||
per-page). System voice + "BUILT BY KEVON BUTLER · DETROIT".
|
||||
- **404** (`app/not-found.tsx`) is the north star — scanlines, crt-sweep, glitch
|
||||
wordmark, amber 404. Interactive CTAs live in client `NotFoundActions` so the
|
||||
page stays a server component (keeps its metadata export).
|
||||
- **RouteStub** (`components/vyndr/RouteStub.tsx`) backs not-yet-built routes
|
||||
(terminal/compare/invite/help/about/notifications). Never stub over a route
|
||||
that already has real content.
|
||||
|
||||
## Active Skills
|
||||
- vyndr-voice (all user-facing output)
|
||||
- prop-analysis (grading methodology)
|
||||
|
||||
Reference in New Issue
Block a user