Theme & Branding Engine
At a glance
A theme engine that turns each tenant's BrandingConfig into scoped CSS variables, ships pre-built archetype themes (modern, classic, sport, minimal), supports header/footer customization and validated custom CSS, and lets club sites inherit federation branding while still picking their own accent. The default theme matches the platform's bottle-green and ivory shadcn system with Fraunces and Inter, giving every new site a polished look on day one.
How it works
Theming is a thin layer on top of the design tokens shared by www and web. Each CmsSite stores a BrandingConfig containing logo URL, primary_color, accent_color, font_pair_id, sender-name and dark-mode preference. On render, the Next.js layout emits a server-rendered `<style>` tag scoped to `[data-tenant-brand="<site.id>"]` that injects CSS variables — `--tenant-brand-primary`, `--tenant-brand-accent`, foreground variants derived via YIQ luminance for AA contrast, and an auto-derived accent (×1.18 lightness) when the editor leaves accent_color blank.
Pre-built theme templates (modern, classic, sport, minimal) are JSON presets that the wizard applies to BrandingConfig in one click; switching themes never destroys the logo or custom colors, only the structural layout choices. Header and footer are configurable via layout presets (six headers including sticky, centered-logo, transparent-hero; six footers including multi-column, social-focused, hidden) so editors don't write code to change shell. Advanced users can inject scoped custom CSS — validated for brace mismatches and warned about `!important` use, version-tracked, and prefixed with the site selector so it cannot leak into other tenants.
Every site is responsive by default with mobile-first breakpoints, and dark mode flips the variable set via the shared ThemeProvider hook. Federation brand inheritance is opt-in per club site: a child site can declare `inherit_from_parent: true` and pick which fields to override, ensuring national visual identity without locking clubs in. The default theme out of the box is the platform's bottle-green primary, ivory surface, Fraunces display and Inter body, giving full shadcn parity with www.petanque.life.
Key capabilities
- Per-site BrandingConfig (logo, colors, font, sender-name) injected as scoped CSS variables
- Pre-built theme templates (modern, classic, sport, minimal) applied non-destructively
- Header and footer layout presets — no code required
- Validated, scoped custom CSS injection for advanced users
- Mobile-first responsive design with dark mode
- Federation brand inheritance with selective field override
- Bottle-green + ivory default theme matching the platform design system
In practice
Sofia, communications lead at the Swedish Federation, wants club sites to feel cohesive without forcing identical branding. She opens the federation theme tab, sets the primary color, the Fraunces+Inter font pair, and the SBF-blue logo. She enables 'Allow inheritance' and tags color and fonts as inheritable.
Klara at BK Hagaberg creates her club site, picks 'Inherit from federation' and overrides only the accent to her club's terracotta. The renderer produces a header that visually echoes the federation while keeping the club's identity. A month later Klara wants a tighter spacing on her hero — she pastes a six-line custom CSS snippet into the advanced tab, the validator warns about one `!important`, she removes it, and the change goes live within the next ISR window.
Features in this subsystem
9| ID | Status | Features |
|---|---|---|
| F18.03.01 | Shipped | Per-site theming (colors, fonts, logo) ✅ 449770bd.m-3 delvis: PUT /v1/cms/sites/{id}/theme — sajtens EGNA färger, den kurerade typografin (GET /v1/cms/font-catalog) och hörnradien, med kontrastdomen (4,5:1 fel inom överlägget, 3:1 varning mot basen) · ⊘ logo_url ägs av F1-9; logo-position/-höjd, favicon och bytes/varianter är ⊘ D-MEDIA-INFRA + m-5 (renderarens chrome-detalj) |
| F18.03.02 | Shipped | Pre-built theme templates (modern, classic, sport, minimal) ✅ 449770bd.m-3 — EXAKT fyra kodägda mallar på GET /v1/cms/theme-templates (+ /{id}) och POST /v1/cms/sites/{id}:apply-theme; classic = plattformens baslinje Fraunces/Inter. Mallen går genom SAMMA validering som en redaktörs egen sparning och rör aldrig custom_css, arvet, menyn eller basens token |
| F18.03.03 | Shipped | Header/footer layout customization ✅ 449770bd.m-3 — PUT …/header-layout (sex presets + sticky/sök/språkväljare) och PUT …/footer-layout (sex presets, länkgrupper med sajtlokala page-mål, kontaktinfo, sociala länkar ur allowlist) · ⊘ nyhetsbrevsflaggan (show_newsletter_signup avvisas — anmälningsformuläret är m-9), höjd/färgöverskrivningar (renderarens tokens, m-5) |
| F18.03.04 | Shipped | Custom CSS injection (for advanced users) ✅ 449770bd.m-3 — PUT/GET …/custom-css med 50 kB-tak, hela den förbjudna listan prövad EFTER normalisering (avvisar, strippar aldrig tyst), url(-allowlist, !important som varning och dry_run (validera utan sparning). Audit-diffen bär storlek + sha256, aldrig texten · ⊘ selektor-skopningen vid rendering är m-5 |
| F18.03.05 | Shipped | Responsive design (mobile-first) ✅ 449770bd.m-3 — PUT/GET …/responsive (breddläge, bredd-preset, max_content_width_px 320—1920, mobil header, mobil fontskalning). Brytpunkterna lagras aldrig — de är husets design-tokens (F1-10), inte en per-sajt-inställning |
| F18.03.06 | Shipped | Dark mode support ✅ 449770bd.m-3 — PUT/GET …/dark-mode med off|light|dark|auto och de FJORTON pinnade färgfälten (mörklägesvarianter CMS:et äger; F1-9 har ingen dark-token) |
| F18.03.07 | Shipped | Federation brand inheritance (club sites can inherit national branding) ✅ 449770bd.m-3 — PUT/GET …/brand-inheritance per aspekt, ETT steg djupt; logo/namn/strategi/custom-CSS alltid barnets; self och direkt A↔B ⇒ 422 circular_inheritance; okänd/annan tenants/raderad förälder ⇒ SAMMA 422 (ingen existensläcka); raderad förälder vid läsning ⇒ 200 + inheritance_broken |
| F18.03.08 | Shipped | Default-tema: bottle-green + ivory, Fraunces display + Inter body ✅ 449770bd.m-3 delvis: classic-mallen ÄR baslinjen (Fraunces/Inter på husets design-tokens) och basens färger kommer ur F1-9:s tenant_theme · ⊘ själva tokenpaketet ägs av F1-10 (packages/shared/src/design/tokens/) |
| F18.03.09 | Planned | Per-portal designprofil (tenant-overridable theme, BrandingConfig) ⊘ F1-9/D-ORGS — tenantens kanoniska token bor i tenant_theme/org_node_theme med sina egna endpoints; D-CMS lägger bara sitt sajt-överlägg ovanpå och skriver aldrig basen |
Stakeholders who need this subsystem
Surfaces in 1 stakeholder analyses