← All posts

how tos · 5 min read

Generate a Tailwind config from any brand's design system

Manually translating design tokens to Tailwind is tedious and error-prone. The generate_tailwind_config MCP tool does it in one call.

There is a specific kind of afternoon you want to avoid: you have a DESIGN.md with every color token, every spacing value, every radius defined. Now you need to get those values into your Tailwind config. So you open tailwind.config.ts, start typing, copy-paste hex values one at a time, and 45 minutes later you have something that might be right and definitely needs to be audited.

This is solved. The generate_tailwind_config MCP tool takes a DESIGN.md and produces a complete, ready-to-paste Tailwind config in one call.

The problem with manual translation

Design tokens and Tailwind configurations are structurally similar but not identical. A DESIGN.md might have:

primary: #635BFF
primary-hover: #5249D4
primary-dark: #4B44C0

Tailwind expects:

colors: {
  primary: {
    DEFAULT: '#635BFF',
    hover: '#5249D4',
    dark: '#4B44C0',
  }
}

That mapping is mechanical, but it requires judgment: which tokens should be nested, which should be flat, what to name the scale steps. And that is just colors. Typography, spacing, radii, shadows, and custom animations each have their own mapping conventions.

When you do this by hand, you introduce inconsistencies. A token called text-secondary in your DESIGN.md might end up as textSecondary in one project and text.secondary in another. Future you, or the next developer, spends time reconciling instead of building.

The Stripe example

The Stripe DESIGN.md is a useful test case because it is a real, dense design system with a full color palette, a specific typography setup, and non-default spacing values.

Running generate_tailwind_config on the Stripe design system produces output like this:

// tailwind.config.ts
export default {
  theme: {
    extend: {
      colors: {
        'stripe-blue': '#635BFF',
        'stripe-dark': '#0A2540',
        'stripe-light': '#F6F9FC',
        success: '#24B47E',
        danger: '#E25950',
        warning: '#E6A817',
        muted: '#6B7C93',
        'surface-1': '#FFFFFF',
        'surface-2': '#F6F9FC',
        'surface-3': '#E3E8EF',
      },
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        mono: ['SF Mono', 'Fira Code', 'monospace'],
      },
      fontSize: {
        'display-lg': ['3.5rem', { lineHeight: '1.1', letterSpacing: '-0.03em' }],
        'display': ['2.5rem', { lineHeight: '1.15', letterSpacing: '-0.025em' }],
        'heading': ['1.5rem', { lineHeight: '1.3', letterSpacing: '-0.02em' }],
        'body-lg': ['1.125rem', { lineHeight: '1.6' }],
        'body': ['1rem', { lineHeight: '1.6' }],
        'caption': ['0.875rem', { lineHeight: '1.5' }],
        'label': ['0.75rem', { lineHeight: '1.4', letterSpacing: '0.05em', fontWeight: '600' }],
      },
      borderRadius: {
        sm: '4px',
        DEFAULT: '6px',
        md: '8px',
        lg: '12px',
        xl: '16px',
      },
      boxShadow: {
        'card': '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',
        'elevated': '0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.05)',
        'modal': '0 20px 60px rgba(0,0,0,0.15)',
      },
    },
  },
};

That is production-ready Tailwind configuration. Paste it in, start using text-stripe-blue, rounded-md, text-heading. Every class maps directly to a design decision from Stripe's system.

How to use it

With the DesignMD MCP server connected:

generate_tailwind_config("stripe")

Or with a local DESIGN.md:

generate_tailwind_config(content: <paste DESIGN.md content>)

The output is formatted as valid TypeScript and handles edge cases: tokens with the same name at different levels get namespaced automatically, numeric scales are sorted correctly, and the extend wrapper is added so you do not accidentally override Tailwind defaults unless the DESIGN.md explicitly replaces them.

Related tools: CSS variables and shadcn themes

The same pipeline has two companion tools:

generate_css_variables — Outputs the same tokens as CSS custom properties for use in plain CSS, vanilla JS projects, or anywhere Tailwind is not in scope:

:root {
  --color-primary: #635BFF;
  --color-primary-hover: #5249D4;
  --font-sans: 'Inter', system-ui, sans-serif;
  --radius-md: 8px;
  /* ... */
}

generate_shadcn_theme — Maps design tokens to shadcn's CSS variable naming convention. If you use shadcn/ui, you need your tokens in --primary, --secondary, --destructive, etc., not arbitrary names. This tool does that mapping and outputs a block you paste directly into your globals.css.

The three tools cover the major outputs you need when adopting a design system: the Tailwind config for utility classes, the CSS variables for raw token access, and the shadcn theme for component library integration.

The actual time saving

A full Stripe-style design system has around 40-60 named tokens across colors, typography, spacing, and effects. Manually translating that to Tailwind takes 30-60 minutes, depending on how careful you are about naming conventions.

The generate tools take about 3 seconds. The output is more consistent than manual work because the mapping is done deterministically from the DESIGN.md source, so the token names in your CSS always match the token names in your design documentation.

The less interesting version of this is: it saves time. The more interesting version is: it keeps your design system and your implementation in sync, because they are both generated from the same source file.