tanjilahmed87@gmail.com

Frontend5 min read

Building a Design System on Tailwind Without It Becoming Spaghetti

Tailwind's flexibility is exactly what turns into inconsistency at scale, unless the design tokens are enforced somewhere other than developer memory.

Tanjil Ahmed

Lead Software Engineer · Notionhive

Tailwind's greatest strength — write any utility class, anywhere — is also how a codebase ends up with fourteen slightly different shades of the same blue and six different border-radius values within a year, if nothing constrains the choices past the developer's memory of the last value they used.

Constrain the theme, not the developer

The fix isn't a style guide document nobody reads — it's a `tailwind.config` that only exposes the design tokens that actually exist in the system: a fixed color palette, a fixed spacing scale, a fixed set of radii. If `rounded-[7px]` isn't a value in the config, it's not a value anyone can accidentally reach for.

  • Define semantic color tokens (`accent`, `muted`, `danger`) instead of exposing the full Tailwind palette.
  • Componentize repeated utility combinations (`card-glow`, `btn-primary`) rather than repeating class strings everywhere.
  • ESLint plugin for Tailwind catches class-order and arbitrary-value drift in code review, not in a design audit six months later.
  • A living Storybook of the actual components beats a static Figma file that drifts from the real implementation.
Tailwind doesn't create inconsistency. An unconstrained theme file does, one arbitrary value at a time.