Web Architecture
Overview
Section titled “Overview”apps/web is a TanStack Start application that mainly does four things:
- Compose the browser/runtime shell.
- Connect the shared
@life-manager/dbdata layer to web-specific services. - Persist web-only UI/runtime state in Zustand where needed.
- Add browser integrations such as PWA, notifications, Sentry, and route prefetching.
The business data model does not primarily live in apps/web. Most domain reads, writes, collections, and types come from @life-manager/db, while shared workflows and formatting helpers live in @life-manager/shared.
Runtime Layers
Section titled “Runtime Layers”TanStack Start request -> `src/start.ts` / `src/server.ts` -> `src/routes/__root.tsx` - global auth lookup via `getAuthUser()` - Mantine / dates / notifications / i18n bootstrapping - devtools, Vercel analytics, Speed Insights -> route branch - public routes (`/`, `/$lang/*`, `/auth/*`) - protected shell (`/_app`) - onboarding (`/new-user`) -> protected routes wrap content with: - `PowerSyncProvider` - `WebCollectionsProvider` - `Shell`App Structure
Section titled “App Structure”src/ routes/ TanStack Router file routes components/ Web UI and shell composition db/ powersync/ Browser PowerSync database + connector queries/ Web-specific query wrappers supabase/ Server/admin Supabase helpers confirmations/ Browser confirmation adapter for collection workflows stores/ Zustand stores for web-only state hooks/ UI orchestration and browser-aware hooks lib/ Toasts, logout cleanup, feature helpers actions/ Server-side auth actions used by TanStack Start utils/ Small browser utilitiesRouting Topology
Section titled “Routing Topology”Routing is file-based and generated into src/routeTree.gen.ts.
| Route area | Role |
|---|---|
__root.tsx | Global document, auth bootstrap, Mantine/providers, analytics/devtools |
index.tsx | Public landing page |
$lang.tsx | Locale gate for localized public content |
$lang/docs/* | Public product docs rendered inside the marketing/docs layout |
$lang/guides/* | Public step-by-step guides |
auth/* | Sign-in and OAuth callback flow |
_app.tsx | Authenticated application entrypoint |
_app/dashboard.tsx | Dashboard |
_app/project/overview.tsx | Work overview / project index |
_app/project/detail.tsx | Work detail page keyed by projectId search param |
_app/finance.tsx | Finance module |
_app/calendar.tsx | Calendar module |
_app/profile.tsx | Profile page |
_app/settings.tsx | Dedicated settings route, mainly for mobile |
_app/habbit-tracker.tsx | Placeholder route |
new-user.tsx | Onboarding/initial profile setup for authenticated users |
api/* | Small server endpoints such as /api/version |
Protected App Boot Sequence
Section titled “Protected App Boot Sequence”src/routes/_app.tsx is the runtime boundary of the authenticated app:
- it disables SSR for the shell route
- it redirects unauthenticated users to
/auth - it mounts
PowerSyncProviderandWebCollectionsProvider - it waits for both PowerSync and the profile query to become ready
- it shows a minimum-duration loading screen to avoid flicker
- it renders
Shellonly after the offline-first layer is usable
/new-user repeats the same provider stack, but renders InitializeProfile instead of the main shell.
Shell Composition
Section titled “Shell Composition”src/components/AppShell/Shell.tsx owns the persistent layout:
- Header with global controls and the time tracker
- Navbar with module navigation
- Main content area
- Aside panel with collapsible contextual content
- Mobile navigation drawer
- Settings modal
- Offline indicator
The shell is also where several app-wide behaviors start:
useProcessRecurringCashflows()useCheckNewVersion()useNotificationHandler()useAppointmentStatusManager()
That makes Shell the operational center of the authenticated UI, not just a layout wrapper.
State Split
Section titled “State Split”Two state families are intentionally separated.
Shared domain state
Section titled “Shared domain state”- Read via
@life-manager/db/queries - Mutated via
@life-manager/db/actions - Backed by PowerSync + Supabase
- Available offline once synced
Web-only runtime state
Section titled “Web-only runtime state”- Stored in Zustand under
src/stores/ - Used for UI preferences, view state, drawers, selected entities, and computed timer snapshots
- Persisted only where it is useful for UX
Browser-First Concerns
Section titled “Browser-First Concerns”PWA and offline behavior
Section titled “PWA and offline behavior”vite.config.ts configures vite-plugin-pwa with:
- precached JS/CSS/fonts/images
- network-first caching for Supabase, PowerSync, and navigation requests
- browser service worker registration in production
RoutePrefetcher then preloads critical authenticated routes after boot to improve offline usability.
Monitoring
Section titled “Monitoring”- Sentry is initialized in both router/client (
src/router.tsx) and server entry (src/server.ts) - Vercel Analytics and Speed Insights are mounted in the root document
- TanStack devtools, router devtools, pacer devtools, recurring-cashflow devtools, and PowerSync diagnostics are exposed in development
Version refresh flow
Section titled “Version refresh flow”useCheckNewVersion() polls /api/version, compares it against window.__BUILD_VERSION__, and shows a persistent refresh notification when a newer build is available.