Work / Chitragupt / Wiki / Decisions
2026-07-02-light-theme-derivative
Decisioncanonicalverified 2026-07-02
DECISION.2026-07-02.LIGHT-THEME-DERIVATIVEDecision
The website ships with a light theme derived by the engineering team from the dark-only wireframes. Toggling is controlled by a class="dark" on <html> — set by a pre-hydration inline script in apps/website/src/app/layout.tsx from localStorage.theme (fallback prefers-color-scheme). Runtime clicks come from a sun/moon toggle in ProfileMenu. Tailwind v4 @custom-variant dark (&:where(.dark, .dark *)) keeps the dark: prefix working.
Semantic tokens live in apps/website/src/app/globals.css:
- Surface:
--bg-app,--bg-elevated,--bg-muted - Foreground:
--fg-default,--fg-muted,--fg-subtle - Border:
--border-default,--border-strong - Accents:
--brand(emerald),--warning(amber),--danger(rose),--family(blue),--ai(purple), each with a-softcompanion.
Light mode uses -600 accent shades on #ffffff / #fafafa surfaces for AA contrast. Dark mode uses -500 accents on #09090b (matches wireframes).
Why
The wireframes are dark-only; a light theme has not been formally designed. Two options were considered:
- Ship dark-only and defer light to a later design pass.
- Ship a light theme derived by engineering with a documented derivation table.
We picked (2) because (a) the class-strategy plumbing lands regardless (theme toggle, prehydration script, semantic tokens), (b) shipping dark-only forces users on light-mode operating systems into an aesthetic they may not want, and (c) the derivation is straightforward — reuse the wireframe's palette semantics, remap accent shades for legibility on white.
The derivation must be reviewed by design at some point. Until then, light mode is functional but not brand-verified.
Impact
- Every component in the dashboard flow now reads semantic tokens; adding a new component in any flow should follow the same pattern (
bg-app,fg-default,border-default,brand, etc.). - Recharts paint attributes read CSS vars via
stroke="var(--brand)"etc. so charts inherit theme. - The seed script + benchmark table are theme-agnostic.
- Future flows (Inbox, Ask, Expense, Portfolio, Tax, Settings, Landing, Auth, Onboarding, Admin) must migrate to the semantic layer in their own refactors. Grep-audit tokens
bg-zinc-950 | text-zinc-100 | border-zinc-800 | bg-emerald-500should trend to zero as flows land.
Related surfaces:
- dashboard-populated
- dashboard-empty
- dashboard-family-combined
- dashboard-family-member
- dashboard-notifications
Status
Active.
Sources
- .context/designs/web/patterns/components.html (dark-only reference palette)
- apps/website/src/app/globals.css (implementation)
Every project of mine is written down like this.
Read the résumé