# How to convert a website into a Tailwind theme

> To convert a website into a Tailwind theme, run `npx designlang <url>`; it writes a Tailwind v3 `tailwind.config.js` and a Tailwind v4 `@theme` CSS file built from the colours, fonts, type scale, spacing, radii and shadows the site actually renders.

Updated 2026-11-03. Page: https://designlang.app/guides/website-to-tailwind-theme

## Steps

1. **Extract the site.** Run npx designlang stripe.com. Both Tailwind files are written to design-extract-output.
2. **Pick your Tailwind version.** Use stripe-com-tailwind.config.js for Tailwind v3, or stripe-com-tailwind-v4.css for Tailwind v4.
3. **Add the theme to your project.** For v3, spread the exported theme into your tailwind.config.js. For v4, import the @theme file in your main CSS instead of importing tailwindcss directly.
4. **Use the generated classes.** Write bg-primary, text-secondary, rounded-md and the extracted spacing steps instead of arbitrary values.
5. **Lint for leftovers.** Run npx designlang check src to find hardcoded values that should use the theme.

Tailwind is only as on-brand as its theme. The defaults are good, and that is the problem: every project and every AI-generated component that uses `bg-blue-600` and `rounded-lg` looks the same. To build in a specific brand, the theme has to hold that brand’s values.

designlang reads a live site and writes the theme for you, in both Tailwind formats. It does not guess from a screenshot. It reads computed styles from the rendered page, so the values are the ones the browser actually paints.

## Generate the theme

```
npx designlang stripe.com
```

Two files in `design-extract-output` matter here:

- `stripe-com-tailwind.config.js` for Tailwind v3 (a JavaScript config).
- `stripe-com-tailwind-v4.css` for Tailwind v4 (a CSS-first `@theme` block).

## Tailwind v3: the config

A trimmed slice of the real stripe.com config. Captured with designlang 13.3.2 on 3 November 2026.

```
/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    extend: {
      colors: {
        primary: {
          '50': 'hsl(248, 98%, 97%)',
          '100': 'hsl(248, 98%, 94%)',
          '500': 'hsl(248, 98%, 50%)',
          '900': 'hsl(248, 98%, 16%)',
          DEFAULT: '#533afd'
        },
        secondary: { /* 50–950 */ DEFAULT: '#061b31' },
        accent: { /* 50–950 */ DEFAULT: '#00d66f' },
        background: '#ffffff',
        foreground: '#061b31'
      },
      fontFamily: { sans: ['sohne-var', 'sans-serif'] },
      spacing: {
        '14': '28px', '16': '32px', '20': '40px', '24': '48px',
        '30': '60px', '32': '64px', '40': '80px', '48': '96px'
      },
      borderRadius: { xs: '1px', sm: '4px', md: '8px', lg: '16px', full: '100px' }
    }
  }
}
```

The `DEFAULT` of each colour is the exact extracted value. The 50 to 950 steps are a ramp generated around it, so you have tints and shades for hover states and backgrounds. Treat the ramp as a starting point: those steps are derived, not read from the site.

To use it, import the file and merge it into your own config:

```
// tailwind.config.js
import brand from './design-extract-output/stripe-com-tailwind.config.js';

export default {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: brand.theme,
};
```

## Tailwind v4: the @theme block

Tailwind v4 moved configuration into CSS. The v4 file is a ready `@theme` block that already imports Tailwind:

```
/* Tailwind v4 @theme — generated by designlang
   site: Stripe | Financial Infrastructure to Grow Your Revenue */

@import "tailwindcss";

@theme {
  --color-primary-50: hsl(248 98% 97%);
  --color-primary-500: hsl(248 98% 50%);
  --color-primary: #533afd;
  --color-secondary: #061b31;
  --color-accent: #00d66f;
  /* fonts, spacing, radii and shadows follow */
}
```

Copy it into your project and import it from your main stylesheet in place of the plain `@import "tailwindcss";` line, so the import is not duplicated.

## What maps to what

| Tailwind key | Comes from |
|---|---|
| `colors.primary`, `secondary`, `accent` | The brand colours, ranked by where and how often they appear on buttons, links and highlights. |
| `colors.background`, `foreground` | The page surface and body text colour. |
| `fontFamily.sans` | The font families in use, most-used first. |
| `fontSize` | Every size in the type scale, with its line height. |
| `spacing` | Spacing values clustered from margins, padding and gaps. |
| `borderRadius` | Distinct corner radii, labelled from xs to full. |
| `boxShadow` | The distinct shadows, smallest to largest. |

## Clean up before you commit

- Spacing on marketing sites is often irregular. stripe.com produced steps such as `340px` and `366px` that are layout widths, not spacing. Delete steps you will not use.
- If the palette is noisy, rerun with `--palette 10` to merge near-duplicates into ten distinct colours.
- Fonts are named as the site loads them (`sohne-var` here). You need a licence and the font files to use a commercial typeface. Swap in a fallback if you do not have one.
- For dark mode, add `--dark`. The dark values are written next to the light ones.
- For a responsive config with per-breakpoint values, add `--responsive-deep`.

## Before and after

This is what the theme changes in practice. A card written against Tailwind defaults, the way an AI editor usually writes it:

```
<div class="rounded-lg bg-white p-6 shadow">
  <h3 class="text-lg font-semibold text-gray-900">Team</h3>
  <button class="mt-4 rounded-md bg-blue-600 px-4 py-2 text-white">Start trial</button>
</div>
```

The same card on the extracted theme. The class names barely change; the values behind them now come from the site:

```
<div class="rounded-lg bg-background p-16 shadow-md">
  <h3 class="font-sans text-foreground">Team</h3>
  <button class="mt-14 rounded-md bg-primary px-20 py-14 text-white hover:bg-primary-600">Start trial</button>
</div>
```

Note that the spacing keys are the extracted ones (`p-16` is 32px here, not Tailwind’s default 64px), because the theme replaces the default scale. If you would rather keep Tailwind’s spacing and only add the brand values, put the generated `spacing` block under `theme.extend` and rename the keys so they do not collide.

## Make the theme stick

A theme only helps if code uses it. Run `npx designlang check src --tokens design-extract-output/stripe-com-design-tokens.json` to find hardcoded hex values, off-scale spacing and wrong fonts, with the nearest token for each. If an AI editor writes most of your UI, connect it to the tokens with the [MCP guide](https://designlang.app/guides/cursor-claude-design-system-mcp) so it uses the theme from the first line.

## Questions

### Does it work with Tailwind v4?

Yes. Every run writes both a v3 `tailwind.config.js` and a v4 `@theme` CSS file.

### Will the classes match the original site’s class names?

No. designlang reads computed values, not class names, and writes them into a standard Tailwind theme. You get `bg-primary`, not the site’s internal utility names.

### Can I use it on my own staging site?

Yes. Pass any URL, including localhost. Add `--insecure` for self-signed certificates and `--cookie` for pages behind a login.

## Related

- [shadcn theme from any website](https://designlang.app/guides/shadcn-theme-from-website)
- [Vercel design system](https://designlang.app/design-system/vercel)
- [Stripe design system](https://designlang.app/design-system/stripe)
- [CLI reference](https://designlang.app/docs/cli-reference)
