Design Token Generator
Pick a few brand colours and the tool builds a complete, production-ready token system: real perceptual 50→950 ramps (not a hard-coded scale), a shadcn-style semantic layer with matching light + dark themes, and a live component preview so you SEE the system before you ship it. Every text/background pair is checked against WCAG contrast, and you can export to CSS variables, Tailwind v4 @theme, Tailwind v3, SCSS, JS/TS, the W3C DTCG format, or Style Dictionary.
About this ToolHow it works, benefits & use casesTap to collapse
Most token generators dump a flat list of CSS variables. This one builds a real two-layer system. Pick a primary, accent, and neutral colour (plus success/warning/error) and it derives a perceptual 50→950 ramp for each — the lightness follows a contrast-friendly curve and saturation eases at the extremes, so the scale is actually derived from your colour instead of hard-coded. On top of the primitives it builds a shadcn/ui-style semantic layer — background, foreground, card, primary, secondary, muted, accent, destructive, border, input, ring — with matching light and dark values, so a component referencing --primary flips themes without touching markup. A live preview renders a real card, buttons, and input in both themes, and every text/background pair is checked against WCAG contrast as you edit. Export to CSS variables, Tailwind v4 @theme, Tailwind v3 config, SCSS, a JS or TypeScript token object, the W3C DTCG format, or Style Dictionary. The whole configuration lives in a shareable URL.
How to Use
- 1Start from a preset palette or set your primary, accent, and neutral colours with the colour pickers.
- 2Adjust the base radius and spacing unit, and set your sans/mono font stacks.
- 3Toggle the live preview between light and dark to see your semantic tokens on a real card and buttons.
- 4Read the contrast audit — it flags any text/background pair below the 4.5:1 WCAG AA threshold.
- 5Pick an export format and copy or download the tokens; share the URL to hand the exact system to a teammate.
Key Benefits
- Perceptual 50→950 ramps actually derived from your colour, not a fixed hard-coded scale
- Two-layer system: primitive ramps plus a shadcn-style semantic layer with light + dark themes
- Live component preview (card, buttons, input) in both light and dark
- WCAG contrast audit on every text/background pair, computed as you edit
- Eight export formats including Tailwind v4 @theme, W3C DTCG, and Style Dictionary
- Adjustable radius, spacing unit, and font stacks
- Shareable URL captures the full token configuration
Common Use Cases
- Bootstrapping a complete token foundation (primitives + semantic + dark) for a new design system
- Generating a shadcn/ui-compatible :root and .dark block from your brand colours
- Exporting a Tailwind v4 @theme or Tailwind v3 config that maps semantic tokens to CSS vars
- Producing a W3C DTCG tokens.json or Style Dictionary source for a token pipeline
- Validating that a dark theme’s muted text actually passes WCAG contrast before shipping
Live preview
- Body text on background14.52AAA
- Card text on card14.52AAA
- Muted text on background3.51AA Large
- Primary button label5.50AA
- Accent button label8.29AAA
- Destructive button label4.95AA
- Secondary button label9.28AAA
CSS variables · light + dark
:root {
/* Primitive colour ramps */
--color-primary-50: #f5f8fc;
--color-primary-100: #e7effb;
--color-primary-200: #c6d9f9;
--color-primary-300: #92b8f7;
--color-primary-400: #4f8ff7;
--color-primary-500: #2473f5;
--color-primary-600: #0b5fe8;
--color-primary-700: #0b4fbf;
--color-primary-800: #0d4196;
--color-primary-900: #0e3574;
--color-primary-950: #0b2349;
--color-accent-50: #f7f5fc;
--color-accent-100: #ede8fa;
--color-accent-200: #d5c6f8;
--color-accent-300: #b192f6;
--color-accent-400: #8351f5;
--color-accent-500: #6426f3;
--color-accent-600: #4f0de6;
--color-accent-700: #420cbd;
--color-accent-800: #370e95;
--color-accent-900: #2e0f73;
--color-accent-950: #1e0c48;
--color-neutral-50: #f8f8f9;
--color-neutral-100: #f1f1f1;
--color-neutral-200: #dedee0;
--color-neutral-300: #c2c2c6;
--color-neutral-400: #a0a0a7;
--color-neutral-500: #888891;
--color-neutral-600: #74747e;
--color-neutral-700: #616169;
--color-neutral-800: #4f4f54;
--color-neutral-900: #3f3f43;
--color-neutral-950: #29292b;
--color-success-50: #f6fbf8;
--color-success-100: #eaf8ef;
--color-success-200: #cbf3da;
--color-success-300: #9decba;
--color-success-400: #62e492;
--color-success-500: #3bdd77;
--color-success-600: #24cf63;
--color-success-700: #1faa52;
--color-success-800: #1d8744;
--color-success-900: #1a6837;
--color-success-950: #124224;
--color-warning-50: #fcfaf5;
--color-warning-100: #fbf3e7;
--color-warning-200: #f9e6c5;
--color-warning-300: #f8d291;
--color-warning-400: #f8b94f;
--color-warning-500: #f6a723;
--color-warning-600: #e9960a;
--color-warning-700: #c07c0a;
--color-warning-800: #97630c;
--color-warning-900: #754e0e;
--color-warning-950: #49320b;
--color-error-50: #fcf5f5;
--color-error-100: #fae8e8;
--color-error-200: #f7c7c7;
--color-error-300: #f39595;
--color-error-400: #f15656;
--color-error-500: #ed2c2c;
--color-error-600: #df1313;
--color-error-700: #b81212;
--color-error-800: #911212;
--color-error-900: #701212;
--color-error-950: #460e0e;
/* Radius, spacing, type */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
--radius-2xl: 16px;
--radius-full: 9999px;
--spacing-0: 0px;
--spacing-1: 4px;
--spacing-2: 8px;
--spacing-3: 12px;
--spacing-4: 16px;
--spacing-6: 24px;
--spacing-8: 32px;
--spacing-12: 48px;
--spacing-16: 64px;
--spacing-24: 96px;
--font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
/* Semantic tokens (light) */
--background: #ffffff;
--foreground: #29292b;
--card: #ffffff;
--card-foreground: #29292b;
--popover: #ffffff;
--popover-foreground: #29292b;
--primary: #0b5fe8;
--primary-foreground: #ffffff;
--secondary: #f1f1f1;
--secondary-foreground: #3f3f43;
--muted: #f1f1f1;
--muted-foreground: #888891;
--accent: #4f0de6;
--accent-foreground: #ffffff;
--destructive: #df1313;
--destructive-foreground: #ffffff;
--border: #dedee0;
--input: #dedee0;
--ring: #2473f5;
}
.dark {
/* Semantic tokens (dark) */
--background: #29292b;
--foreground: #f8f8f9;
--card: #3f3f43;
--card-foreground: #f8f8f9;
--popover: #3f3f43;
--popover-foreground: #f8f8f9;
--primary: #2473f5;
--primary-foreground: #29292b;
--secondary: #4f4f54;
--secondary-foreground: #f8f8f9;
--muted: #4f4f54;
--muted-foreground: #a0a0a7;
--accent: #6426f3;
--accent-foreground: #29292b;
--destructive: #ed2c2c;
--destructive-foreground: #f8f8f9;
--border: #4f4f54;
--input: #4f4f54;
--ring: #4f8ff7;
}
Start from a palette
Colours
Shape & type
Adds a .dark semantic layer (and prefers-color-scheme block in Tailwind v4).
Export format
Tokens, not a colour dump
A design token system has two layers. Primitives are the raw scale — primary-500, neutral-200. Semantic tokens (background, foreground, primary, border) give those values meaning and are what your components actually reference, so a single token can flip between light and dark without touching markup.
Why the contrast check matters
A dark theme that looks fine can still fail WCAG — muted grey text on a dark surface is the usual culprit. The preview audits every text/background pair against the 4.5:1 AA threshold so you catch it here, not in an accessibility report later.
Was this tool helpful?
Share Your Experience
Help others discover this tool!
Related tools
- Tailwind Config GeneratorVisually build a Tailwind config - theme extend, colors, spacing, fonts, screens, plugins - and export it as a v3 JS config or a v4 @theme CSS block
- CSS Variables GeneratorDesign CSS custom properties as typed tokens with light & dark values, scale generators, and a live preview — export :root CSS, SCSS, Tailwind v4 @theme, or a JS token map
- Changelog GeneratorGenerate changelog from Git commit history
- Heroku Procfile GeneratorBuild a Heroku Procfile and matching app.json — process types, env vars, addons, dyno formation — plus a Procfile parser and audit
- Markdown TOC GeneratorGenerate table of contents for Markdown
- Package.json Scripts GeneratorGenerate common npm scripts for different project types and workflows
Each base colour is converted to HSL, then an 11-step ramp (50 through 950) is built by holding the hue and walking lightness down a fixed, contrast-friendly curve while easing saturation off at the very light and very dark ends so the scale never goes muddy or washed out. Because it derives from your input, two different brand blues produce two genuinely different ramps — unlike the older approach that pinned most shades to a hard-coded scale.
Primitives are the raw scale — primary-500, neutral-200, error-600. Semantic tokens give those values a role: background, foreground, card, primary, border, ring, and so on. Your components reference the semantic tokens, so the same --primary can resolve to one ramp step in light mode and a different one in dark mode. That indirection is what lets a whole UI switch themes by toggling a class, without editing any component.

