Main navigation shell (#20) #66
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!66
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "20-navigation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #20.
Summary
app/(app)/route group hosts the authenticated app surface with a shared chrome (top nav + content container). The(app)segment is part of the source path, not the URL —app/(app)/profile/page.tsxmaps to/profile.app/(app)/layout.tsxrenders<TopNav />then amax-width: 72remcontent container. CSS variables from ADR-0008 throughout; the layout looks coherent in both shipped themes.app/(app)/components/top-nav.tsxis a"use client"component with the five nav links (Profile, Skills, Experience, Projects, Network) + the embedded theme switcher. UsesusePathname()for active-link detection.<Placeholder title ticket blurb />component so when each feature ticket lands it replaces the call with real content. Each placeholder names the tracking ticket(s) (epic #4 / issue #21, etc.)./notesmoved fromapp/notes/toapp/(app)/notes/so it inherits the chrome and matches the future shape feature surfaces will follow. Not in the main nav (it's a reference, not a feature) but reachable by URL. Its internal styling was reduced (no more page-owned background / min-height / max-width) so it fits inside the shell.app/page.tsx(the public landing) no longer mounts the theme switcher — it now lives in the nav shell. Unauth visitors get OS-matched themes viaprefers-color-schemeper ADR-0008. The landing copy points first-time users atPOST /api/auth/registerand then/profile.Keyboard accessibility
<nav aria-label="Main">+<ul>of<a>(via Next.js<Link>), in tab order.aria-current="page"set on the active link.<a>focus rings preserved — inline styles don't stripoutline, so keyboard users see a visible focus indicator without a custom CSS rule.role="radiogroup"/role="radio"from #19.Build / route summary
/offlinestill○ (Static)is the load-bearing thing — the nav layout lives only under(app)/, so the root layout and/offline's precachability stay untouched.What didn't change
Test plan
npm run typecheck/npm run lint/npm test— all green (119 / 32 skipped).npm run build— succeeds. Route summary above.npm run dev— manual probes:/,/profile,/skills,/experience,/projects,/network,/notes,/offline→ all 200./profile,/skills,/notes→ 401 (default-deny intact)./profileHTML contains<nav aria-label="Main">, the five links in order,aria-current="page"set on Profile (the active link), the theme switcher embedded in the nav, and the placeholder content with the tracking ticket link.🤖 Generated with Claude Code