Theming
Every restaurant on SMACKZ ships with a fully customizable theme that drives colors, typography, button styles, border radii, and spacing across every customer-facing surface — websites, native apps, and the dynamic page renderer. Themes are stored as JSON in the database and resolved at render time on both web and mobile.
V1 — Current System
V1 themes derive a 200+ token ThemeJSON from a small ThemeConfigInput:
| Field | Purpose |
|---|---|
background |
Canvas color (light/dark scheme inferred) |
text |
Primary text color |
accent |
Brand color (drives CTAs, headings, bands) |
font |
Single font family |
borderRadius |
Single global radius |
The generator (generateThemeJSON in shared-core/src/utils/theme.ts) expands these into the full token tree consumed by web (mapThemeToCssVariables) and mobile (SMACKZ-MOBILE/src/features/pages/).
This is sufficient for single-color brands but cannot express multi-tier brand palettes, context-scoped fonts, or paired button variants for light vs. dark surfaces — gaps that prompted the V2 effort.
V2 — Starbucks-Tier Dynamic Theming
Theme System V2 is a Draft FRD (2026-04-25) that expands the schema, renderer, and admin UI across four pillars while remaining 100% backward compatible: every V1 theme renders byte-identical until an admin opts into a V2 field.
What V2 Adds
- Colors: 4-tier brand palette (
primary,accent,deep,soft,light); 5-role surface spectrum (canvas,card,quiet,banded,inverted); opacity-layered text tokens (textOnLight.{strong,soft},textOnDark.{strong,soft}); 10-step alpha ladders for black + white; reserved-context accents (e.g.,goldfor Rewards-only); opt-ingradientPolicy: "off". - Typography: 10-level semantic scale (display → micro); third context-font slot; semantic
letterSpacingTokensandlineHeightTokens; "weight-as-hierarchy" mode; theme-controlled mobile scale factor. - Border radius: Per-component radii (
card,modal,button,input,badge); semantic aliases (pill,circle,square); asymmetric per-corner strings. - Buttons: Seven variants (
filled,outline,text,filledOnDark,outlineOnDark,circle,tab); auto-pairing onsurfaceRole: "banded"; active-state tokens (activePressScale,transitionDuration); themeable button sizes map.
Section-Level Opt-Ins
Two section properties unlock V2 features without touching the global theme:
| Property | Effect |
|---|---|
surfaceRole |
Picks one of the 5 surface roles. banded auto-switches buttons to filledOnDark / outlineOnDark. |
context |
Names a contextual color/font bag (e.g., rewards, loyalty). Renderer resolves heading colors and fonts from that bag. |
Phasing
| Phase | Scope |
|---|---|
| 1 | Schema expansion (shared-core, version → 2) |
| 2 | Web/mobile renderers 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) |
Where Themes Are Used
- Smackz-Websites — restaurant marketing/ordering sites.
- SMACKZ-MOBILE — customer mobile app (theme passed via
route.params.theme). - Page Renderer — embedded preview in admin and standalone preview at
localhost:5176. - Payment Page — checkout WebView reads
theme=light|darkfrom URL. - Smackz-Admin — theme editor with live preview.
Key Files
| Concern | Path |
|---|---|
| Schema (single source of truth) | shared-core/src/pages/types/theme.ts |
| Generator + ThemeJSON shape | shared-core/src/utils/theme.ts |
| Web CSS var mapping | mapThemeToCssVariables in shared-core/src/utils/theme.ts:801 |
| Typography defaults & resolver | shared-core/src/pages/logic/typographyScale.ts |
| Button variant enum | shared-core/src/pages/types/enums.ts:44 |
| 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 |
| V1 architecture doc | docs/Theme-Architecture.md |
| V2 FRD | docs/Theme-System-V2-FRD.md |
| V2 Design | docs/Theme-System-V2-Design.md |
| V2 Gap Analysis | docs/Theme-System-V2-Gap-Analysis.md |