How to Export DESIGN.md Tokens to Tailwind v4 CSS Format

Use the design.md CLI with the --format css-tailwind flag to convert DESIGN.md tokens into a Tailwind v4-compatible @theme CSS block that maps design system categories to CSS variables.

The google-labs-code/design.md repository provides a deterministic CLI pipeline for exporting design tokens. When you export DESIGN.md tokens to Tailwind v4 CSS format, the tool validates token names against CSS identifier rules and serializes the design system into a pure CSS @theme block suitable for modern Tailwind configurations.

Installation and Prerequisites

The CLI requires Node.js ≥ 20 or Bun. Install the package globally or in your project to access the design.md binary.

npm install -g @google/design.md

CLI Export Workflow

Basic Command Structure

The design.md export command located in packages/cli/src/commands/export.ts reads a DESIGN.md file and emits the token set in your chosen format. For Tailwind v4, specify css-tailwind as the format target.

design.md export path/to/DESIGN.md --format css-tailwind > tailwind-theme.css

This command writes the @theme CSS block to stdout, which you can redirect to a file for integration into your stylesheets.

Input Options

Use - as the file path to read from standard input, enabling piping from other processes.

cat DESIGN.md | design.md export - --format css-tailwind

Token Validation and Exit Codes

The CLI validates every token name against the CSS identifier regex /^[a-zA-Z0-9][a-zA-Z0-9-]*$/. If validation fails, the command exits with a non-zero status, making it safe for CI pipelines and pre-commit hooks.

Integrating with Tailwind v4

Tailwind v4 consumes @theme blocks directly. Import the generated CSS file into your Tailwind configuration to register the design tokens as CSS variables accessible within the framework.

// tailwind.config.js
const fs = require('fs');
const path = require('path');

module.exports = {
  plugins: [
    function ({ addBase }) {
      const css = fs.readFileSync(path.resolve(__dirname, 'tailwind-theme.css'), 'utf8');
      addBase(css);
    },
  ],
};

Programmatic Node.js API

For custom build pipelines, invoke the emitter and serializer directly without spawning child processes. This approach uses the pure functions exposed by the @google/design.md package.

import { readFile } from 'fs/promises';
import { lint } from '@google/design.md/linter';
import { TailwindV4EmitterHandler } from '@google/design.md/linter/tailwind/v4/handler';
import { serializeToCss } from '@google/design.md/linter/tailwind/v4/serialize';

const designMd = await readFile('./DESIGN.md', 'utf8');
const report = lint(designMd);

const emitter = new TailwindV4EmitterHandler();
const result = emitter.execute(report.designSystem);

if (!result.success) {
  throw new Error(result.error.message);
}

const css = serializeToCss(result.data.theme);
console.log(css);

Technical Implementation Details

Parsing and Linting Stage

In packages/cli/src/commands/export.ts, the readInput function loads the source file and the lint function constructs a DesignSystemState object representing the parsed design system with all token categories extracted.

Tailwind v4 Emitter Handler

The TailwindV4EmitterHandler class in packages/cli/src/linter/tailwind/v4/handler.ts validates token names and maps design system categories—colors, typography, border-radius, and spacing—into a plain TailwindV4ThemeData object. This handler is pure (no side effects) and deterministic, producing the same output for identical inputs.

CSS Serialization

The serializeToCss function in packages/cli/src/linter/tailwind/v4/serialize.ts walks the ordered CATEGORIES list and writes each entry as a CSS variable inside an @theme block. The emitter outputs a string that the CLI prints to stdout in packages/cli/src/commands/export.ts.

Summary

  • Install the @google/design.md CLI and run design.md export --format css-tailwind to generate a Tailwind v4 @theme CSS block.
  • Token names are validated against /^[a-zA-Z0-9][a-zA-Z0-9-]*$/ to ensure CSS identifier compatibility.
  • The pipeline uses TailwindV4EmitterHandler and serializeToCss from the packages/cli/src/linter/tailwind/v4/ directory to produce deterministic output safe for CI environments.
  • Integrate the generated CSS into your Tailwind v4 configuration using the addBase plugin function or by importing the CSS file directly into your stylesheet.

Frequently Asked Questions

What is the correct format flag for exporting to Tailwind v4?

Use --format css-tailwind. This flag triggers the TailwindV4EmitterHandler which validates tokens and outputs the @theme CSS block required by Tailwind v4.

How does the CLI validate token names before export?

The emitter validates every token name against the regex /^[a-zA-Z0-9][a-zA-Z0-9-]*$/ to ensure compliance with CSS identifier rules. Invalid names cause the export to fail with a non-zero exit code.

Can I export tokens from standard input instead of a file?

Yes. Pass - as the file path to read from stdin: design.md export - --format css-tailwind. This is useful for piping content in CI/CD pipelines.

Where are the core Tailwind v4 emitter functions located?

The main logic resides in packages/cli/src/linter/tailwind/v4/handler.ts for the emitter handler and packages/cli/src/linter/tailwind/v4/serialize.ts for the CSS serialization. The CLI entry point is packages/cli/src/commands/export.ts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →