A single account syncing heart rate from a watch took the worker down within half an hour. The status cards' graded series read the last 91 days of raw rows, bounded in time but not in rows, so a stream sampled every minute or faster materialised six or seven figures of objects on every refresh and the read ran into the statement timeout. Add readDayAggregates, which folds one type into per-day sum, count, min and max in Postgres (optionally split into age segments and filtered to the metric's plausibility domain), and move the readers that folded raw rows into days in memory onto it: the graded series (recent, weekly and the cold-tier fallback, for every type), the vitals day-mean fallback behind the personal band, the tiered context's recent days and the plan review. Recent, weekly and monthly buckets are identical to the raw fold; the cold-tier yearly slope now runs over day means. On 91 days of per-minute pulse the graded series now allocates 1.6 MB where it allocated 62 MB, while the raw read alone holds 22 MB. A structural guard freezes the remaining untaken measurement reads in the worker and insight directories: each must name a sparse literal type or carry a listed reason. Refs #1023
src/app/
The Next.js App Router tree: the page surfaces a logged-in user sees and the REST API under api/. Server components are the default; "use client" is added only where a hook, state, or browser API needs it. Routing is file-based — a page.tsx is a page, a route.ts is an API endpoint.
API routes (api/)
Every endpoint wraps its handler in apiHandler (@/lib/api-handler), parses any body with Zod safeParse, narrows userId from the session or Bearer token (never from the body), and returns the { data, error, meta? } envelope. requireAdmin() is cookie-only, so api/admin/ is unreachable by Bearer token. Notable groups:
auth/— login, register, password, passkey (WebAuthn), refresh, Codex device-OAuth.measurements/,mood-entries/,medications/,sleep/— the core health-data CRUD + batch/bulk ingest.ingest/— external Bearer-token ingest surfaces.insights/,analytics/,dashboard/— AI insights, the Coach SSE stream, trend summaries, the first-paint dashboard snapshot.withings/,whoop/,fitbit/,integrations/,sync/— OAuth connect/sync/webhook surfaces and the offline delta feed.fhir/,share-links/,doctor-report/,export/,import/— clinician-facing FHIR R4 read API, shareable records, report + data export.notifications/,devices/,send/,telegram/— channel registration, device tokens, dispatch, webhook intake.admin/— operator panel APIs (cookie-only).health/,version/,meta/,internal/— health check, build-version probe, runtime metadata, worker-internal routes.
Page surfaces
measurements/, medications/, mood/, insights/, achievements/, notifications/, settings/, onboarding/, admin/, plus the public about/, privacy/, bugreport/, the share-record route c/, and the root dashboard (page.tsx). Shared shell + chrome lives in layout.tsx; error.tsx / global-error.tsx / not-found.tsx / loading.tsx cover the framework boundaries. layout.tsx holds the one nonce-bound dangerouslySetInnerHTML (theme bootstrap).
Conventions
See ../../CLAUDE.md. The request-flow walk in .planning/codebase/arch.md annotates each layer with file:line citations. Related dirs: handlers compose ../lib/; pages render ../components/.