Wealthpath (networth-app) · Part 4 of 6

Client tour: pages, shared state, and the app shell

Client tour: pages, shared state, and the app shell

All 15 pages, what shared state holds and why, how forms and charts stay consistent, and what makes the app installable and themed.

2026-09-04beginnerNext.js 14, React 18, React Query, Recharts
  • nextjs
  • react
  • react-query
  • pwa
  • beginners

Pages are components

Backend done, numbers trustworthy — now the face. The naive client fetches per page and the screens disagree with each other; what breaks is the user’s trust in every number at once. This part tours fifteen pages fed from one shared state, then Part 5 removes the server entirely and watches what survives.

In React, the UI is built from components — reusable pieces like buttons, cards, and charts that combine into pages. Next.js turns files into pages by convention: src/app/forecast/page.tsx becomes the /forecast URL. Fifteen routes ship:

Route What you see
/dashboard Hero net worth, journey chart, recap, milestones, health score, next move, insights
/portfolio Allocation pie, liquidity buckets, drift from targets
/assets, /liabilities, /goals Lists with create/edit forms
/forecast Projected wealth with sliders you can drag
/fi FI calculator (Lean/Traditional/Fat/Barista) + Monte Carlo bands
/scenarios Saved what-if comparisons
/cashflow Income/expense/investment entries + monthly totals
/checkin The 4-step monthly wizard
/tools Stateless calculators (SIP, EMI, compound, inflation…) — no saving, just math
/tools/import Spreadsheet upload: auto-map columns, preview the plan, commit
/settings Country, currency, assumptions, local-mode toggle, login, backup/sync
/privacy Export backup, wipe everything

Every page sits inside an AppShell: sidebar on desktop, bottom nav on mobile, title bar on top. One shell, fifteen contents — navigation, fonts, and theme stay consistent for free.

Why shared state exists

Without shared state, each page would fetch its own copy of the data and they would disagree. NetWorthContext is the single copy: it loads assets, snapshots, and goals once, then derives everything else with memoized selectors — latest snapshot per asset, monthly aggregates, per-category breakdowns. Components read from it instead of fetching.

Two supporting tools: React Query caches server fetches (5-minute freshness, one retry) so lists don’t refetch on every click, and react-hook-form + zod validate forms with the same schemas the API uses — one definition of “valid,” shared by frontend and backend.

The wizard, step by step

The check-in is four screens — values, changes, notes, review — driven by a step number (1–4) plus per-asset entries. Next/Back move the step; on step 4, Next becomes Submit, which posts each entry as a snapshot, clears the form, and refreshes shared state. A progress bar shows (step − 1) / 3. If you own no assets yet, the wizard sends you to /assets first — the flow refuses to run on empty data.

Charts, theme, installability

All seven charts are Recharts (React-friendly chart components) with one global style override, so every chart matches. The visual identity is a warm-paper theme with bronze accents and gold in dark mode, Inter for headings and JetBrains Mono for numbers. The app is installable (PWA): a manifest plus a service worker that precaches the shell routes — API calls try the network first with an offline fallback, pages load from cache. That is why airplane mode still shows your data.

Open by construction

No page requires login — the only sign-in lives inside Settings, purely for cloud sync. Anyone with the URL and the machine sees everything. That is not an oversight; it follows from the privacy constraint in Part 1 (no cloud dependency means no gatekeeper). Local-first means the machine is the trust boundary.

In Part 5 we go deeper on the two hardest backend topics: working with no server at all, and syncing safely when a server exists.