Narong's "Settings content should load on the right instead of jumping to a different page" complaint, fixed by lifting the nav rail + page header into a Next.js layout shared across every settings sub-route. Clicking a built sub-page (Payment Methods, Diff Reasons, Customer Display) now swaps only the right pane — the rail stays mounted across navigations.
test-nix-os-87-prod.mjs. Tested by tagging the rail's DOM node with a data-test-rail-id attribute on first visit, then navigating through all four built sections and re-asserting the same node still bears the tag — proves the layout-level rail isn't unmounting/remounting between routes.
app/(authed)/settings/layout.tsx — server component. Owns the page-level <h1>Settings</h1> + subtitle, the requirePermission("nix_cafe.settings.view") gate, and the getCurrentTenant() lookup. Wraps a client <SettingsNav> next to {children} in a 220px / 1fr grid._components/settings-nav.tsx — client component, derives active state from usePathname(). Strips /cafe basePath so matching works in the deployed Worker. 12 nav items: 4 link to real routes, 8 stay greyed-disabled placeholders. aria-current="page" applied to the active row.h1 text-2xl + per-page subtitle (now in layout). Each section's old h1 demoted to h2 text-lg for visual hierarchy: layout "Settings" (big) → section name (smaller) → cards. Touched page.tsx, payment-methods/page.tsx, payment-methods/starter-client.tsx, payment-diff-reasons/diff-reasons-client.tsx, display/display-branding-client.tsx.nix_cafe.settings.view or re-fetch the tenant lookup. The redundant code path that was repeated 4× is now in one place.| Suite | Score | Status |
|---|---|---|
| test-nix-os-87-prod (this bundle) | 11/11 | PASS |
| test-phase4-prod | 10/10 | PASS |
| test-receipt-fixes-prod | 6/6 | PASS |
| test-phase1-prod | 11/11 | PASS |
| Total | 38/38 | PASS |
First receipt-fixes-prod run flaked at 2/6 (transient — looked like Cloudflare warm-up); re-ran clean at 6/6. Pattern noted in the receipt-fixes session memory as well: when the FIRST step of a Playwright prod test times out, always retry once before debugging.
nix-cafe (no backend touched, no DB migration): app/(authed)/settings/layout.tsx NEW (server) app/(authed)/settings/_components/settings-nav.tsx NEW (client) app/(authed)/settings/page.tsx stripped header + nav app/(authed)/settings/payment-methods/page.tsx h1 → h2 app/(authed)/settings/payment-methods/starter-client.tsx h1 → h2 app/(authed)/settings/payment-diff-reasons/diff-reasons-client.tsx h1 → h2 app/(authed)/settings/display/display-branding-client.tsx h1 → h2 Commit: 7d24500