One Symfony codebase, three design systems: the --dp-* vs --tpl-* token contract
Three brands from one codebase only works if CSS tokens follow a clear contract. How MFP separated channel config (--dp-*) from template look (--tpl-*) — and what that buys.
One Symfony codebase, three design systems: the --dp-* vs --tpl-* token contract
The problem: three brands, one codebase
At MFP, three consumer brands — ditpetje.nl (caps), dithorloge.nl (watches) and ditparfum.nl (perfume) — run from a single Symfony codebase. Each brand has its own visual identity: ditpetje is sporty and colourful, dithorloge is luxury and serif-leaning, ditparfum is boutique and minimal. Without a clear CSS token contract, that path leads inevitably to channel-specific overrides in every template, copy-paste CSS, and a builder who has to remember every change in three places.
The split: --dp-* vs --tpl-*
The recently formalised approach in MFP separates CSS tokens into two categories:
--dp-*(config tokens) — properties set per channel inchannel.{id}.yaml: brand colour, brand font, accent colour, gradient direction. These tokens come from configuration and apply across the whole channel regardless of template.--tpl-*(template tokens) — properties tied to a template's visual variant:--tpl-hero-bg,--tpl-tile-radius,--tpl-price-font. These live in template CSS and govern how a specific layout behaves — independent of the channel.
Together they form a matrix: a sporty template on ditpetje gets --dp-* from the ditpetje config and --tpl-* from the sporty template. A luxury template on dithorloge gets --dp-* from dithorloge and --tpl-* from luxury. Two dimensions that do not contaminate each other.
What the three 2026 templates actually do
The recent "2026 polish" cycle pushed the contract through all three templates:
- Sporty 2026 — prominent hero, tile discount chip, nav underline, mono footer. Tight geometry, vivid accent.
- Luxury 2026 — serif hero typography, a spec-sheet style PDP, borderless tiles. Calm cohesion, explicit typographic hierarchy.
- Boutique 2026 — ambient gradient background, serif prices, square tiles. Hand-curated feel with space around.
None of these choices live in an if-this-channel statement. All three are template tokens, defined in a channel-independent way. A fourth brand landing tomorrow and choosing the luxury template inherits the spec-sheet PDP immediately, without a single template CSS line needing to change.
Why it was formalised now
Token contracts often arise retroactively, after a team has burned itself enough times on per-channel CSS sprawl. That is what happened in MFP: after three 2026 template cycles it became clear that without an explicit naming-prefix contract every new variant would pile on top of the old one. The refactor (TEN phase 2 in the tickets) put the contract on paper — literally as CSS comments and naming conventions — and rewrote the existing templates against it. Every new colour, every new spacing step, now carries a prefix that tells you instantly where it belongs.
The payoff arrives at the next channel
The real return on a good token contract is not visible at the first three channels. It is visible at the fourth. Adding a new brand to MFP under this contract is a configuration action: create channel.4.yaml, fill in --dp-* values, choose a template, run seed:channel. No editing of template CSS, no introduction of if-channel blocks, no review cycle to check whether a colour is hard-coded somewhere. That is what a good contract buys: time at the moment you need it most.
Share this article
Curious what is possible?
One conversation is usually enough to tell whether it fits. A reply within 24 hours, and no middlemen.