07 — Design Tokens
07 — Design Tokens
Section titled “07 — Design Tokens”“Wijzig je een brand color → alles downstream past zich automatisch aan. Één bron, oneindige consistentie.”
Het design token systeem is de technische backbone van Beam’s visuele identiteit. Alles wat er visueel gebeurt — de editor, blocks, addons, AI-gegenereerde content, exports — leest uit één bron: het token schema.
Inhoudsopgave
Section titled “Inhoudsopgave”- Theming Cascade
- Drie-Laags Token Architectuur
- Style Pack ↔ Token Schema Alignment
- Guardrail Systeem
- Semantic Context Laag
- Volledig Token Schema
- Publieke Token API
- Storage Structuur
- Export Formaten
- Technische Beslissingen
- Backlog
1. Theming Cascade
Section titled “1. Theming Cascade”Tokens cascaderen van laag naar hoog. Hogere lagen overschrijven lagere.
Laag 5 │ User Overrides (styling builder: handmatige aanpassingen) │ Altijd de hoogste prioriteit — de gebruiker wint │Laag 4 │ Vertical Pack Styling │ Niche-specifieke overrides (Yoga Studio's warme radius) │Laag 3 │ Style Packs (gilde-gebaseerd) │ "Healer Calm", "Creator Bold", "Merchant Trust" │ = het startpunt dat de styling builder aanbiedt │Laag 2 │ Addon Global Styles │ CSS variabelen, fonts die addons meebrengen │Laag 1 │ Beam Core Tokens │ Platform defaults — de basis die altijd geldt │────────┤ │Tokens │ W3C Design Token Schema (single source of truth) │ Alles hierboven resolved naar dit schemaCascade-regel: Laag 1 en 2 zijn read-only vanuit de styling builder. De builder bewerkt Laag 3 (Style Pack keuze), Laag 4 (vertical pack overrides) en Laag 5 (user overrides).
2. Drie-Laags Token Architectuur
Section titled “2. Drie-Laags Token Architectuur”Brand Tokens → Semantic Tokens → Element Tokens(ruwe waarden) (betekenis/rol) (toepassing)
#1B4D7A → primary color → button backgroundPlayfair Display → heading font → h1, h2, h36px → base radius → card cornerTokens werken altijd via refs — nooit hardcoded waarden. Wijzig je een brand color → alles downstream past zich automatisch aan via OKLCH shade recalculatie.
3. Style Pack ↔ Token Schema Alignment
Section titled “3. Style Pack ↔ Token Schema Alignment”De styling builder is het bewerkoppervlak, het token schema is de opslag, en de Style Pack is het distributieformaat voor het addon systeem. Dezelfde data, drie representaties.
StylePack (addon systeem) Token Schema (styling builder)───────────────────────── ────────────────────────────────colors.brand → tokens.colors.brand.primarycolors.primary → tokens.colors.semantic.primarycolors.accent → tokens.colors.brand.accentcolors.surface → tokens.colors.semantic.surfacecolors.text → tokens.colors.semantic.textcolors.muted → tokens.colors.semantic.text-mutedfonts.heading → tokens.typography.fonts.headingfonts.body → tokens.typography.fonts.bodyborderRadius → tokens.shape.radius.presetspacing → tokens.shape.spacing.presetcomponentStyles → elements.* (button, table, etc.)seasonal.overrides → meta.seasonal_overrides4. Guardrail Systeem
Section titled “4. Guardrail Systeem”“You cannot make it ugly” is geen aspiratie — het is een technische implementatie. Guardrails zijn altijd actief, niet optioneel.
Kleur Guardrails
Section titled “Kleur Guardrails”| Regel | Implementatie | Feedback |
|---|---|---|
| Max 3 brand colors | UI blokkeert 4e kleur | ”Drie kleuren zijn genoeg voor een sterk merk.” |
| WCAG AA contrast | Real-time check bij elke kleurwijziging | Contrast ratio badge: ✅ AA / ⚠️ Bijna / ❌ Onvoldoende |
| Harmonie check | Kleuren buiten OKLCH-gegenereerde schaal worden gewaarschuwd | ”Deze kleur botst met je palette. Probeer deze suggestie.” |
| Dark mode contrast | Automatisch gevalideerd bij generatie | Idem |
Typografie Guardrails
Section titled “Typografie Guardrails”| Regel | Implementatie | Feedback |
|---|---|---|
| Curated font-paren | Alleen vooraf goedgekeurde combinaties heading+body | Font picker toont compatibele matches |
| Geen extreme sizes | Min/max per element type (H1: 1.5rem–4rem) | Slider stopt bij grenzen |
| Line-height validatie | Automatisch berekend op basis van font size | Niet handmatig instelbaar tenzij “geavanceerd” |
| Mobile sizes | Automatisch afgeleid uit desktop (ratio) | Preview toont mobiel altijd mee |
Vorm Guardrails
Section titled “Vorm Guardrails”| Regel | Implementatie | Feedback |
|---|---|---|
| Consistente radius | Eén radius-preset voor alles, sm/base/lg zijn afgeleid | Geen losse radius per element |
| Spacing systeem | Base unit × vermenigvuldigers, geen vrije waarden | Spacing slider met stappen |
| Shadow coherentie | Drie niveaus (sm/md/lg), niet vrij instelbaar | Shadow preset selector |
Guardrail Feedback — Nintendo Juice
Section titled “Guardrail Feedback — Nintendo Juice”Guardrails voelen niet als restrictie maar als hulp:
| Situatie | Visueel | Audio |
|---|---|---|
| Kleur voldoet aan WCAG AA | Subtiel groen vinkje | Zacht “ding” |
| Kleur faalt contrast | Kleur schudt licht + suggestie slide-in | Zacht “bonk” |
| Font-paar is harmonieus | Fonts schuiven soepel in positie | — |
| Radius verandert | Alle elementen animeren smooth mee (spring physics) | Subtiel “click” per stap |
| Kleurwijziging propageert | Ripple-animatie door alle gerelateerde tokens in sidebar | Toon (pitch volgt hue) |
5. Semantic Context Laag
Section titled “5. Semantic Context Laag”Tokens zijn contextbewust. Een primary kleur op een donkere achtergrond gebruikt automatisch een lichtere variant:
"primary": { "default": { "ref": "brand.primary" }, "on-dark": { "ref": "tokens.colors.generated.primary-300" }, "on-light": { "ref": "tokens.colors.generated.primary-700" }}Beam lost dit automatisch op op basis van de achtergrondkleur van de container — onzichtbaar voor de gebruiker, ingebakken in het schema.
6. Volledig Token Schema
Section titled “6. Volledig Token Schema”{ "brand": { "name": "Bouwbedrijf De Vries", "logo": { "url": "https://r2.beam.app/sites/abc123/brand/logo.svg", "favicon": null } },
"tokens": { "colors": { "brand": { "primary": "#1B4D7A", "secondary": "#F5F0EB", "accent": "#D4883E" }, "semantic": { "primary": { "default": { "ref": "brand.primary" }, "on-dark": { "ref": "tokens.colors.generated.primary-300" }, "on-light": { "ref": "tokens.colors.generated.primary-700" }, "dark-mode-override": null }, "background": { "value": "#FFFFFF", "dark-mode-override": "#0F172A" }, "surface": { "value": "#F8F9FA", "dark-mode-override": "#1E293B" }, "text": { "value": "#1A1A2E", "dark-mode-override": "#F1F5F9" }, "text-muted": { "value": "#6B7280", "dark-mode-override": "#94A3B8" }, "border": { "value": "#DEE2E6", "dark-mode-override": "#334155" }, "danger": { "value": "#C92A2A" }, "success": { "value": "#2F9E44" }, "warning": { "value": "#E67700" } }, "generated": { "primary-50": "auto (OKLCH)", "primary-100": "auto (OKLCH)", "primary-200": "auto (OKLCH)", "primary-300": "auto (OKLCH)", "primary-400": "auto (OKLCH)", "primary-500": "auto (OKLCH)", "primary-600": "auto (OKLCH)", "primary-700": "auto (OKLCH)", "primary-800": "auto (OKLCH)", "primary-900": "auto (OKLCH)" } },
"typography": { "fonts": { "heading": { "family": "Playfair Display", "source": "google" }, "body": { "family": "Lato", "source": "google" }, "mono": { "family": "JetBrains Mono", "source": "google" } }, "scale": { "h1": { "font": "heading", "size": { "desktop": "3rem", "mobile": "2.25rem" }, "weight": 700, "lineHeight": 1.2 }, "h2": { "font": "heading", "size": { "desktop": "2.25rem", "mobile": "1.875rem" }, "weight": 600, "lineHeight": 1.3 }, "h3": { "font": "heading", "size": { "desktop": "1.875rem", "mobile": "1.5rem" }, "weight": 600, "lineHeight": 1.3 }, "h4": { "font": "heading", "size": { "desktop": "1.5rem", "mobile": "1.25rem" }, "weight": 500, "lineHeight": 1.4 }, "h5": { "font": "heading", "size": { "desktop": "1.25rem", "mobile": "1.125rem" }, "weight": 500, "lineHeight": 1.4 }, "h6": { "font": "heading", "size": { "desktop": "1rem", "mobile": "1rem" }, "weight": 500, "lineHeight": 1.4 }, "body": { "font": "body", "size": { "desktop": "1rem", "mobile": "1rem" }, "weight": 400, "lineHeight": 1.6 }, "label": { "font": "body", "size": { "desktop": "0.875rem", "mobile": "0.875rem" }, "weight": 500, "lineHeight": 1.4 }, "caption": { "font": "body", "size": { "desktop": "0.75rem", "mobile": "0.75rem" }, "weight": 400, "lineHeight": 1.4 } } },
"shape": { "radius": { "preset": "balanced", "sm": "4px", "base": "6px", "lg": "10px", "pill": "9999px" }, "spacing": { "preset": "normal", "base": "4px" }, "shadow": { "preset": "subtle", "sm": "0 1px 2px rgba(0,0,0,0.05)", "md": "0 4px 6px rgba(0,0,0,0.07)", "lg": "0 10px 15px rgba(0,0,0,0.1)" } } },
"elements": { "button": { "primary": { "bg": { "ref": "semantic.primary.default" }, "text": { "value": "#FFFFFF" }, "border": { "value": "transparent" }, "radius": { "ref": "shape.radius.base" }, "paddingX": "1.25rem", "paddingY": "0.625rem", "font": { "ref": "typography.scale.label" }, "states": { "hover": { "bg": { "ref": "tokens.colors.generated.primary-700" } }, "focus": { "ring": { "ref": "semantic.primary.default" }, "ringOffset": "2px" }, "disabled": { "opacity": 0.5 }, "loading": { "opacity": 0.8 } } }, "secondary": { "bg": { "ref": "semantic.surface" }, "text": { "ref": "semantic.primary.default" }, "border": { "ref": "semantic.border" }, "radius": { "ref": "shape.radius.base" }, "states": { "hover": { "bg": { "ref": "tokens.colors.generated.primary-50" } } } }, "ghost": { "bg": { "value": "transparent" }, "text": { "ref": "semantic.primary.default" } }, "destructive": { "bg": { "ref": "semantic.danger" }, "text": { "value": "#FFFFFF" } } }, "table": { "headerBg": { "ref": "semantic.surface" }, "borderColor": { "ref": "semantic.border" }, "stripeColor": { "ref": "tokens.colors.generated.primary-50" }, "cellPadding": "0.75rem 1rem" }, "list": { "markerColor": { "ref": "semantic.primary.default" }, "itemSpacing": "0.375rem", "indent": "1.5rem" }, "input": { "border": { "ref": "semantic.border" }, "radius": { "ref": "shape.radius.base" }, "focusRing": { "ref": "semantic.primary.default" }, "bg": { "value": "#FFFFFF" } }, "badge": { "radius": { "ref": "shape.radius.pill" }, "font": { "ref": "typography.scale.caption" } }, "codexCard": { "bg": { "ref": "semantic.surface" }, "border": { "ref": "semantic.border" }, "radius": { "ref": "shape.radius.lg" }, "titleFont": { "ref": "typography.scale.label" }, "rarityGlow": { "ref": "semantic.primary.default" } } },
"meta": { "version": "2.0", "onboarding_completed_at": "2026-02-14T12:00:00Z", "last_published_at": null, "source_mood": "professional-warm", "source_font_preference": "classic-serif", "source_gilde": "healer", "source_class": "guide", "style_pack_id": "healer-calm", "token_format": "w3c-design-tokens-draft", "seasonal_overrides": null, "guardrails": { "contrast_aa_pass": true, "color_harmony_pass": true, "font_pair_validated": true, "last_checked_at": "2026-02-14T12:00:00Z" } }}7. Publieke Token API
Section titled “7. Publieke Token API”Elk Beam-merk heeft een read-only token endpoint. De pagebuilder, AI content generator, addon blocks, Codex kaart-rendering en externe tools lezen hier live uit.
GET /api/sites/{site_id}/tokens→ Volledig token schema in W3C formaat
GET /api/sites/{site_id}/tokens/css→ CSS variables, kant-en-klaar voor embedden
GET /api/sites/{site_id}/tokens/resolved→ Alle refs opgelost, cascade toegepastTokens zijn de bron — CSS, Tailwind en W3C JSON zijn afgeleiden.
8. Storage Structuur
Section titled “8. Storage Structuur”CF R2: beam-media/ sites/ {site_id}/ media/ ← afbeeldingen (onboarding + media library) fonts/ ← eigen WOFF2 uploads brand/ ← logo, faviconNoot over fonts: Curated Google Fonts worden geladen via de Google Fonts API. Eigen WOFF2 uploads worden opgeslagen in R2 (sites/{site_id}/fonts/).
9. Export Formaten
Section titled “9. Export Formaten”Alle exports zijn afgeleiden van het token schema.
1. CSS Variables
:root { --color-primary: #1B4D7A; --color-primary-50: /* OKLCH gegenereerd */; --font-heading: 'Playfair Display', serif; --radius-base: 6px;}2. Tailwind v4 (@theme)
@theme { --color-primary: #1B4D7A; --font-heading: 'Playfair Display'; --radius-base: 6px;}3. W3C Design Tokens JSON Primair formaat. Compatibel met Figma Tokens, Style Dictionary, Canva (via Figma bridge).
4. Style Pack formaat
Export als StylePack interface voor het addon systeem:
{ id: 'custom-my-brand', name: 'Mijn Merk', gilde: 'healer', colors: { brand: '#1B4D7A', primary: '#1B4D7A', accent: '#D4883E', ... }, fonts: { heading: { family: 'Playfair Display', ... }, body: { ... } }, borderRadius: 'medium', spacing: 'comfortable', componentStyles: { /* resolved element tokens */ }}10. Technische Beslissingen
Section titled “10. Technische Beslissingen”| Onderwerp | Beslissing |
|---|---|
| Color shade algoritme | OKLCH via culori library |
| Dark mode | Auto-generatie met handmatige override per token |
| Font bronnen | Curated subset Google Fonts + eigen WOFF2 upload → R2 |
| Tailwind export | v4 CSS-first via @theme |
| Token formaat | W3C Design Token spec als primair formaat |
| Publiceren | Draft staat met aparte publiceer stap |
| Versioning | Auto-save + named snapshots |
| Responsive typografie | Vaste sizes per breakpoint (desktop + mobiel apart) |
| Component states | Hover + focus handmatig, disabled + loading automatisch afgeleid |
| Scope | Per site — geen multi-site (agency feature: backlog B9) |
| Theming cascade | Laag 1-5 systeem: Core → Addon → Style Pack → Vertical → User |
| Guardrails | Altijd actief, niet optioneel — kern-feature |
| Style Pack formaat | Bi-directioneel: StylePack ↔ Token Schema |
| Seasonal overrides | Ondersteuning voor tijdgebonden token-aanpassingen |
| Gilde-awareness | Builder kent het gilde en past suggesties aan |
11. Backlog
Section titled “11. Backlog”Hoog (logische volgende stap na MVP)
Section titled “Hoog (logische volgende stap na MVP)”| # | Feature | Omschrijving |
|---|---|---|
| B1 | Brand health score | Live indicator hoe consistent tokens worden toegepast. Hardcoded waarden buiten token systeem verlagen de score. |
| B2 | Token import | W3C JSON importeren vanuit Figma Tokens, Style Dictionary of andere Beam site |
| B3 | ”Gebruikt in” impact preview | Toon waar een token gebruikt wordt vóór je het wijzigt. “Deze kleur zit in 3 pagina’s, 2 buttons, 1 tabel.” |
Medium
Section titled “Medium”| # | Feature | Omschrijving |
|---|---|---|
| B4 | Brand lock / permissions | Agency vergrendelt primaire kleur + logo, klant past de rest aan. |
| B5 | Changelog / audit trail | Leesbare geschiedenis: “Angelo heeft op 14 feb de primary color gewijzigd.” |
| B6 | AI stijlgeneratie vanuit URL | Voer een inspiratie URL in → Beam extraheert stijl als token startpunt. |
| B7 | Animaties & transitions | Globale instelling: transition snelheid + easing preset. |
| B8 | Fluid typography | clamp() per breakpoint als alternatief voor vaste sizes. |
Later / Visie
Section titled “Later / Visie”| # | Feature | Omschrijving |
|---|---|---|
| B9 | Agency / multi-site templates | Gedeelde token templates over meerdere sites. |
| B10 | Real-time samenwerking | Meerdere gebruikers tegelijk in de styling builder. |
| B11 | Tokens overdraagbaar naar andere platforms | E-mail templates, Canva social media, pitch decks. |
| B12 | AI als merkbewaker | AI toetst elke nieuwe pagina aan de merkidentiteit. |
| B13 | Semantische betekenislaag | Tokens beschrijven niet alleen hoe iets eruitziet maar wat het betekent. “Blauw = vertrouwen.” |