Theme System V2 FRD
Status: Draft, 2026-04-25 Source files:
docs/Theme-System-V2-FRD.md,docs/Theme-System-V2-Design.md,docs/Theme-System-V2-Gap-Analysis.mdCompanion: Theming domain page, Theme-Architecture.md (V1)
Background
The current SMACKZ theming system (V1) generates 200+ token ThemeJSON from a small ThemeConfigInput (background + text + accent + 1 font + 1 radius). This is structurally insufficient for brands that ship rich design systems (Starbucks, Sweetgreen, Chipotle, McDonald's), all of which use multi-tier brand palettes, context-scoped fonts, and paired button variants for light vs. dark surfaces.
Theme System V2 closes those gaps without breaking any existing theme.
The Four Pillars
V2 expands every pillar of the design system. Existing V1 themes render byte-identical until an admin opts into a V2 field.
Colors
- 4-tier brand palette —
primary,accent,deep,soft,light(vs. single-accent derivation). - 5-role surface spectrum —
canvas,card,quiet,banded,inverted. - Opacity-layered text —
textOnLight.{strong,soft}andtextOnDark.{strong,soft}(defaults:rgba(0,0,0,0.87)/rgba(0,0,0,0.58)/rgba(255,255,255,1)/rgba(255,255,255,0.70)). - 10-step alpha ladders for both black and white (10–90%).
- Reserved-context accents — e.g., gold for Rewards-only, scoped per
contextname. - Gradient policy — opt-in
colors.gradientPolicy: "off"to disable the default heavy gradient overlay.
Typography
- 10-level semantic scale — display, jumbo, heroLarge, h1–h4, body, small, micro (vs. current 6-level).
- Third context-font slot — semantically scoped families (e.g., serif for Loyalty, script for heritage moments).
- Semantic letter-spacing/line-height tokens —
normal,loose,looser,compactconsumed per level. - "Weight-as-hierarchy" mode — H1 and H2 share size, differentiate by weight + color.
- Theme-controlled mobile scale factor — replaces hardcoded
TEXT_NUMERIC_PX_SCALE = 1.3.
Border Radius
- Per-component radii —
card,modal,button,input,badge(vs. one global value). - Semantic aliases —
pill→9999px,circle→50%,square→0. - Asymmetric per-corner strings — e.g.,
"12px 12px 0 0"for top-rounded tabs.
Buttons
- Seven variants —
filled,outline,text,filledOnDark,outlineOnDark,circle,tab(vs. current three). - Dark-surface auto-pairing — sections with
surfaceRole: "banded"auto-switch filled/outline → filledOnDark/outlineOnDark. - Active-state tokens —
activePressScale(default 0.95),transitionDuration(default 200ms). - Themeable button sizes map —
normal,large,xlarge→paddingX,paddingY,fontSize. - First-class text-variant tokens —
color,hoverColor,underline.
Backward Compatibility
Every existing V1 theme renders pixel-identical until an admin opts into a V2 field. The migration generator (generateThemeJSON) derives sensible defaults for all new fields from V1 inputs; readers check version and apply conditional logic. Schema is purely additive — old readers skip unknown fields.
Success criterion: ≥95% of production themes render with zero pixel difference; ≥5 themes adopt V2-only features within 60 days of GA.
Phasing
| Phase | Scope |
|---|---|
| 1 | Schema expansion (shared-core, version → 2) |
| 2 | Renderers (web/mobile) behind GrowthBook flag |
| 3 | Section schema (context, surfaceRole) added to yum API |
| 4 | Admin UI panels behind editor flag |
| 5 | Migration + GA (backfill, dual-read, docs) |
Implementation Pointers
| Concern | Files |
|---|---|
| Schema (single source of truth) | shared-core/src/pages/types/theme.ts |
| Generator + ThemeJSON shape | shared-core/src/utils/theme.ts |
| Typography defaults & resolver | shared-core/src/pages/logic/typographyScale.ts |
| Button variant enum | shared-core/src/pages/types/enums.ts:44 |
| Section schema (display props) | shared-core/src/pages/types/section.ts, yum API |
| Web CSS var mapping | mapThemeToCssVariables in shared-core/src/utils/theme.ts:801 |
| Mobile renderer theme consumption | SMACKZ-MOBILE/src/features/pages/ |
| Admin theme editor UI | Smackz-Websites/src/pages/themes/, ThemeOverrideEditor.tsx |
| Reference Starbucks fixture | shared-core/src/pages/fixtures/starbucks-style-theme.json |