The day-grouped list read the newest `limit` raw rows (the web asked for 5000), folded them into days and returned every day at once: one page of thousands of rows, and every day older than the 5000th raw row missing without a word. The sleep list did the same at a year. Both now pick the page in Postgres. The day mode selects the page's local days with the distinct-day total from `COUNT(*) OVER ()` in the same query, then folds only those days into per-source groups in SQL and lets the source ladder choose among the groups, so no raw row reaches the process. The sleep mode cuts sessions with the same gap rule as the reconstruction, pages wake days the same way and reads only the page's stage rows; the 365-day cut and `meta.windowFrom` are gone. A sleep page holds at most 1000 nights, echoed in `meta.limit`. The web list pages both modes at 25 like the per-sample list. The `partial` day marker is dropped from the contract; no day is cut any more. Refs #1245
src/components/
React components. The UI primitives are shadcn/ui (new-york style, zinc base) over Radix + Tailwind 4 + Lucide; everything above the primitives is feature-grouped by surface. Components are server components unless they need a hook, state, or browser API, in which case they open with "use client". Charts use Recharts 3 — replacing the chart library requires explicit approval.
Primitives and shell
ui/— shadcn/ui primitives (button, dialog, sheet, table, …). Generated by the shadcn CLI; keep edits minimal and on-style.layout/— the app shell: sidebar, topbar, bottom nav.providers.tsx,version-poller.tsx— top-level context providers and the self-healing stale-shell poller.i18n/— translation context + locale switcher.
Feature groups
insights/— insight status, assessment cards, Coach surface, advisor cards (the largest group).medications/— medication cards, the schedule wizard, intake timeline, detail history.settings/— the section components behind each settings page.measurements/,mood/,dashboard/— entry forms, lists, dashboard tiles.charts/— Recharts wrappers.monitoring/— Umami / GlitchTip client bootstrap.gamification/,targets/,comparison/,doctor-report/,clinician/,onboarding/,admin/— the remaining per-surface groups.
Conventions
Kebab-case filenames; React component exports stay PascalCase regardless. (A handful of PascalCase-filename outliers under medications/ + onboarding/ are pre-existing drift, noted in ../../CLAUDE.md.) Every t() call needs a matching key in messages/en.json — guarded by i18n-call-site-coverage.test.ts. Data reads go through TanStack Query with keys from @/lib/query-keys and unwrap (await res.json()).data. Tests live in __tests__/.