1 min read

Designing with tokens

How every surface in this boilerplate stays on-theme — one set of semantic tokens, no hard-coded colors, and components that restyle themselves when the theme changes.

designui

Every color in this boilerplate is a semantic token: background, foreground, muted, primary, border. Components never name a color — they name a role, and the theme decides what that role looks like.

That one rule is why swapping the entire look of the app is a change to a single CSS file.

Why semantic tokens

Hard-coded colors rot. The first text-gray-500 looks harmless; six months later there are forty of them, dark mode ships, and half of them are wrong in ways nobody notices until a screenshot lands in a customer deck.

Tokens invert the problem. A component says text-muted-foreground — "de-emphasized text" — and both themes carry their own answer for what that means.

The palette lives in one file

packages/ui/src/styles/globals.css defines every token twice: once under :root for light, once under .dark. Nothing else in the repo declares a color.

Components stay ignorant

A card is bg-card text-card-foreground. It has no idea whether it renders on marketing white or dashboard black, and that ignorance is the feature.

Radius and spacing follow the same rule

The corner radius scale derives from a single --radius variable. Want a sharper product? Change one line and every button, card, and dialog follows.

What this buys you

  • Re-theming is a config change, not a migration.
  • Dark mode is correct by construction, not by audit.
  • New components inherit the design language for free — if it only uses tokens, it cannot be off-brand.

The discipline costs nothing when you start and is nearly impossible to retrofit. Start with it.