Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions docs/CODEBASE-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,16 @@ embeds the demo documents once per server and uploads the files in the backgroun
the landing or sign-in pages, which don't need the API; they still ping it so it's warm by the time the app opens).

## 7b2. App frame and navigation (frontend)
- The signed-in pages live in the route group `app/(app)/` (URLs unchanged: `/dashboard`, `/analytics`, ...).
- The signed-in pages live in the route group `app/(app)/`: `/home`, `/spending`, `/bills`, `/receipts`
(`?tab=documents|import|review`), `/ask`, `/settings`. The old URLs (`/dashboard`, `/analytics`, `/ai-analytics`,
`/chatbot`, `/documents`, `/import`, `/review`, `/upload`) redirect to them in `next.config.js` (temporary 307s, query
strings carried). Until UI revamp Phase 5, Spending, Bills and Receipts reuse the old pages' `*Content.tsx`.
- **Sidebar** (`components/app-sidebar.tsx`): Home · Track (Spending, Bills & subscriptions) · Receipts & statements
(badge = flagged review items) · Ask Lumen (Ctrl/⌘+K). It collapses to a 56px icon rail with Ctrl/⌘+B, remembered
in the `sidebar_state` cookie. The layout reads that cookie on the sidebar's first render, which is always
client-side because the auth guard shows a loader on the server, so there's no jump and no server read. Shortcuts
skip key presses in text fields (`isTypingTarget` in `lib/utils.ts`). **Account** (Settings, API keys, Log out) is the
top-right `components/avatar-menu.tsx`.
`app/(app)/layout.tsx` holds the auth guard, sidebar and top bar; they mount once and stay while you move between
pages, so only the content area swaps. `app/(app)/template.tsx` fades each page's content in (`.app-page-in` in
`globals.css`). `components/dashboard-shell.tsx` is just a page's content wrapper and optional header card.
Expand All @@ -268,7 +277,10 @@ embeds the demo documents once per server and uploads the files in the backgroun
- **No layout shift from overlays.** `globals.css` sets `scrollbar-gutter: stable` and cancels Radix's scroll-lock
margin (`body[data-scroll-locked]`), so opening a menu or dialog never moves the page. Guarded by
`npm run test:e2e` (Playwright, local only), which drives the dev-only harness `app/dev/layout-shift` (404 in
production). Firefox is opt-in with `E2E_FIREFOX=1`.
production). Firefox is opt-in with `E2E_FIREFOX=1`. `html, body` use `overflow-x: clip`, never `hidden`:
`hidden` makes `<body>` a scroll container whose scrollbar disappears when a menu opens.
- **Signed-in e2e:** `e2e/fixtures.ts` `signIn(page)` fakes a Supabase session (localStorage) plus the
`lumen_session` cookie, and stubs every backend call, so `e2e/shell.spec.ts` drives the real shell without servers.
- **Motion:** use `motion/react` only (framer-motion was removed). Shared timings live in `lib/motion.ts`
(`DURATION`, `EASE_OUT`, `fadeUp`). Reduced motion is honoured globally by `MotionConfig reducedMotion="user"`
in the app layout and a CSS rule in `globals.css`.
Expand Down
14 changes: 14 additions & 0 deletions docs/direction/STORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,17 @@ with the numbers and the files that prove them. Newest last. Raw numbers live in
12 e2e checks pass, including portal colours, AA contrast for muted text (4.9:1), login staying dark and
reduced motion. framer-motion was removed. Story point: reproduce in a test first. Here the test environment
was hiding the very bug.

## 27. The new app shell, and the second half of the shifting-page bug (UI revamp, Phase 1)
- **S:** The sidebar still had the November-2025 tabs ("Workspace", "Compare", a test link), so its labels no longer
matched what the app does. The Phase 0 fix had also left Ask Lumen shifting 15 px once in about four runs.
- **T:** Ship the new navigation (Home · Track · Receipts · Ask) with old URLs still working. Collapse to an icon
rail without a jump on reload. Find the remaining shift.
- **A:** Added a Playwright fixture that fakes a signed-in session and stubs the backend, so the real shell is
testable without servers. A probe showed `<body>` owning its own 15 px scrollbar: `overflow-x: hidden` on html and
body turns body into a scroll container, and a menu's scroll lock removes that scrollbar. Switched to `overflow-x:
clip`. The collapsed state is read on the sidebar's first (client-only) render, so app pages stay static on Vercel.
- **R:** 31 e2e checks pass, including 8 redirects, auth on all new routes, a rail on first paint, shortcuts ignored
while typing, a live review badge and the mobile sheet closing. Avatar-menu shift checks passed 24/24 on repeat
(failed 1 in 4 before). Story point: a flaky test is a bug report. Here it caught the half of the original bug
that the first fix missed.
Loading
Loading