Eén Symfony-codebase, drie design-systemen: het --dp-* vs --tpl-* token-contract

Drie merken vanuit één codebase werkt alleen als CSS-tokens een duidelijk contract volgen. Hoe MFP de scheiding aanbracht tussen kanaal-config (--dp-*) en template-look (--tpl-*) — en wat dat oplevert.

Eén Symfony-codebase, drie design-systemen: het --dp-* vs --tpl-* token-contract

Een witte reisstekker met één kop erop en twee andere koppen ernaast; de drie voeten zijn gelijk

Het probleem: drie merken, één codebase

Bij MFP draaien drie consumentenmerken — ditpetje.nl (petten), dithorloge.nl (horloges) en ditparfum.nl (parfum) — vanuit één Symfony-codebase. Elk merk heeft een eigen visuele identiteit: ditpetje is sportief en kleurrijk, dithorloge is luxe en serif-georiënteerd, ditparfum is boutique en minimalistisch. Zonder een duidelijk CSS-tokencontract leidt dat onvermijdelijk tot kanaal-specifieke overrides in elke template, copy-paste-CSS en een bouwer die elke aanpassing op drie plekken moet onthouden.

De scheiding: --dp-* vs --tpl-*

De recent geformaliseerde aanpak in MFP scheidt CSS-tokens in twee categorieën:

  • --dp-* (config-tokens) — eigenschappen die per kanaal zijn ingesteld in channel.{id}.yaml: brand-color, brand-font, accent-color, gradient-direction. Deze tokens komen uit configuratie en gelden voor het hele kanaal, ongeacht template.
  • --tpl-* (template-tokens) — eigenschappen die horen bij de visuele variant van een template: --tpl-hero-bg, --tpl-tile-radius, --tpl-price-font. Deze tokens leven in de template-CSS en bepalen hoe een specifieke layout zich gedraagt — onafhankelijk van het kanaal.

De combinatie levert een matrix op: een sporty-template op ditpetje krijgt --dp-* uit de ditpetje-config en --tpl-* uit de sporty-template. Een luxury-template op dithorloge krijgt --dp-* uit dithorloge en --tpl-* uit luxury. Twee dimensies die elkaar niet besmetten.

Wat de drie 2026-templates concreet doen

De recente "2026-polish"-cyclus drukte het contract door alle drie de templates:

  • Sporty 2026 — een prominente hero, tile-discount-chip, navigation underline, mono footer. Strakke geometrie, levendig accent.
  • Luxury 2026 — serif hero-typografie, een spec-sheet stijl PDP, randloze tegels. Kalme cohesie, expliciete typografische hiërarchie.
  • Boutique 2026 — ambient-gradient achtergrond, serif prijzen, vierkante tegels. Hand-curated gevoel met ruimte rondom.

Geen van deze keuzes leeft in een if-this-channel-statement. Alle drie zijn template-tokens, op een kanaal-onafhankelijke manier gedefinieerd. Een vierde merk dat morgen aanlandt en de luxury-template kiest, krijgt direct de spec-sheet-PDP zonder dat één template-CSS-regel hoeft te veranderen.

Waarom dit nu werd geformaliseerd

Token-contracten ontstaan vaak retroactief, nadat een team voldoende vaak verbrand is door per-channel CSS-sprawl. In MFP gebeurde dat ook: na drie 2026-template-cycli werd duidelijk dat zonder explicit naam-prefix-contract iedere nieuwe variant het oude erbij ging schoppen. De refactor (TEN-fase 2 in de tickets) zette het contract op papier — letterlijk in CSS-comments en naming-conventions — en herschreef de bestaande templates ernaar. Elke nieuwe kleur, elke nieuwe spacing-stap, krijgt nu een prefix die meteen vertelt waar hij hoort.

De waarde komt bij het volgende kanaal

Het echte rendement van een goed token-contract blijkt niet bij de eerste drie kanalen. Het blijkt bij het vierde. Een nieuw merk toevoegen op MFP is met dit contract een config-actie: channel.4.yaml aanmaken, --dp-*-waarden invullen, een template kiezen, seed:channel draaien. Geen template-CSS bewerken, geen if-channel-blokken introduceren, geen review-cyclus om te checken of een kleur ergens hard-coded is. Dat is wat een goed contract koopt: tijd op het moment dat die het hardst nodig is.

Benieuwd wat er mogelijk is?

Eén gesprek is vaak genoeg om te weten of het past. Binnen 24 uur een reactie, en zonder tussenpersonen.

  • Reactie binnen 24 uur, altijd persoonlijk
  • Na een half uur bellen weet u de orde van grootte
  • Vrijblijvend eerste gesprek, geen verplichtingen
  • Ook voor bestaande software van een andere partij