Design Tokens Are a Contract, Not a Color Palette
This post started as a note to my future self. Every few months I relearn the same lessons about design tokens, so this time I'm writing them down.
When we finally measured, the numbers were worse than anyone guessed. Around 42% of the time spent on a typical change went into working around design tokens rather than building anything.
The problem
We had good intentions. We even had a document describing how design tokens should work. The trouble was that the document and the code had quietly gone their separate ways.
The setup was ordinary: Playwright at the edges, TypeScript doing most of the heavy lifting, and a handful of scripts nobody wanted to own. It worked well until usage roughly doubled over a single quarter.
The fix
The fix turned out to be smaller than expected. Instead of adding another layer, we removed one and leaned on what Playwright already gives you out of the box.
The core of it looks like this:
.card-list {
container-type: inline-size;
}
@container (min-width: 36rem) {
.card {
display: grid;
grid-template-columns: 12rem 1fr;
gap: 1.5rem;
}
}
Nothing about this is clever, and that's the point. Anyone on the team can read it in a minute and know exactly what it does.
A few things that helped along the way:
- Pair on the first few changes so the knowledge doesn't live in one head.
- Delete dead code aggressively; it's the cheapest refactor there is.
- Keep the old path around until the new one has survived a real incident.
- Measure before and after, even if it's just a rough number in a spreadsheet.
Trade-offs
We still haven't solved server-side rendering. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.
The biggest cost was social, not technical. Changing how people think about design tokens takes much longer than changing the code.
Takeaways
If you take one thing away from this, let it be this: design tokens is a design decision, not a cleanup task. Make it early and make it on purpose.