·1 min read

Why Design Tokens Matter

Tailwind v4 @theme on this TanStack Start site — what to share, what to leave local, and when a token is not worth it.

Design SystemsCssTailwind

Design tokens name colors, type, spacing, radius, and shadow once. On a personal site the win is restyle without grepping the whole repo — not an enterprise design system.

Before tokens

A color change meant hunting one-off utility strings. A type tweak meant deciding every body class by hand. Tokens point utilities at one definition. Markup still looks like Tailwind; values resolve to shared CSS variables.

Tailwind v4 @theme

Tokens live in src/styles.css next to the rest of the system:

@theme {
  --color-sky-tint: #ebf5ff;
  --color-ink: #0a0d12;
  --font-sans: 'Geist Variable', ui-sans-serif, system-ui, sans-serif;
  --radius-xl: 12px;
}

Tailwind generates bg-sky-tint, text-ink, rounded-xl. Redesign becomes a token list edit, not a scattered class rewrite.

Subtlety: day-cycle sky colors remapped via [data-day-luma] must use plain @theme, not @theme inline. inline bakes hex into utilities so runtime overrides never apply. Plain @theme keeps var(--color-*) so contrast can flip with the sky.

Practical limits

Tokenize values used three or more times, or likely to change. One-off colors, radii, or shadows do not need a name. If you cannot name a token without a paragraph of context, leave it local.

This site keeps a small set — surfaces, text steps, focus, a few radii and shadows (DESIGN.md). Most UI uses a handful. That ratio is the test.

Migration order that worked

  1. Inventory colors and type sizes used more than twice.
  2. Move into @theme with boring names (ink, graphite, dusk-violet).
  3. Replace utilities section by section — not one unreviewable commit.
  4. Leave true one-offs until they repeat.

Then sky or tracking is a single edit. Components stay ordinary Tailwind + shadcn/ui. Tokens cut thrash; they should not invent a second styling language.

← All notes