How to Export DESIGN.md Tokens to Tailwind v4 CSS Custom Properties
The design.md CLI converts DESIGN.md token definitions into Tailwind v4 compatible CSS @theme blocks using the --format css-tailwind flag, emitting CSS custom properties that Tailwind v4 consumes natively.
The google-labs-code/design.md repository ships with a purpose-built toolchain for managing design tokens in Markdown. When working with Tailwind v4, you can export DESIGN.md tokens directly to the CSS @theme format, enabling seamless integration of your design system into the utility-first framework without manual variable mapping.
Prerequisites
Install the design.md CLI globally using your preferred package manager. The tool requires Node.js ≥ 20 or Bun.
npm install -g @google/design.md
# or
bun add @google/design.md
CLI Method: Quick Export
The fastest way to export tokens is using the export command with the css-tailwind format. This parses your DESIGN.md file, validates all token names against CSS identifier rules, and outputs a complete @theme block.
design.md export path/to/DESIGN.md --format css-tailwind > tailwind-theme.css
- Use
-instead of a file path to read from STDIN. - The command exits with a non-zero status if any token fails validation (e.g., contains characters not matching
/^[a-zA-Z0-9][a-zA-Z0-9-]*$/). - The output is deterministic and safe to run in CI pipelines.
Example:
design.md export ./examples/totality-festival/DESIGN.md --format css-tailwind > ./totality-theme.css
Programmatic Method: Node.js Integration
For custom build pipelines, import the linting and emission modules directly. The API is pure (no I/O side effects), making it ideal for testing and automation.
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';
// 1. Load DESIGN.md text
const designMd = await readFile('./examples/totality-festival/DESIGN.md', 'utf8');
// 2. Lint and build the design system state
const report = lint(designMd);
// 3. Emit Tailwind v4 theme data
const emitter = new TailwindV4EmitterHandler();
const result = emitter.execute(report.designSystem);
if (!result.success) {
throw new Error(result.error.message);
}
// 4. Serialize to CSS @theme block
const css = serializeToCss(result.data.theme);
console.log(css);
Understanding the Export Pipeline
The export process follows a strict three-stage pipeline implemented in packages/cli/src/commands/export.ts. Each stage is isolated and testable.
Parsing and Linting
The readInput function ingests the source Markdown, while lint constructs a DesignSystemState object containing validated maps for colors, typography, border-radius, and spacing.
Tailwind v4 Emission
In packages/cli/src/linter/tailwind/v4/handler.ts, the TailwindV4EmitterHandler class validates every token name against CSS identifier rules. It transforms the DesignSystemState into a plain TailwindV4ThemeData object, mapping design system categories to Tailwind-compatible theme keys.
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. This produces standard CSS custom properties that Tailwind v4 references automatically.
Integrating with Tailwind v4
Import the generated CSS file into your project. Tailwind v4 natively recognizes @theme blocks, making the variables available to utility classes.
/* main.css */
@import './tailwind-theme.css';
@import 'tailwindcss';
Alternatively, load the CSS programmatically in your build configuration if you need to process it through additional PostCSS steps.
Summary
- Install the CLI with
npm install -g @google/design.md(requires Node ≥ 20). - Export via CLI using
design.md export <file> --format css-tailwind. - Validate token names automatically against CSS identifier rules (
/^[a-zA-Z0-9][a-zA-Z0-9-]*$/). - Use programmatically by importing
TailwindV4EmitterHandlerandserializeToCssfrom the@google/design.mdpackage. - Consume in Tailwind v4 by importing the generated
@themeblock into your CSS entry point.
Frequently Asked Questions
What Node.js version is required to run the exporter?
The design.md CLI requires Node.js 20 or higher, or alternatively Bun. This ensures native support for modern file system APIs and module resolution used in the export pipeline.
Can I export DESIGN.md tokens to Tailwind v3 format?
The css-tailwind format specifically targets Tailwind v4's native @theme CSS block. For Tailwind v3, you would need to construct a JavaScript theme object manually or use a different emission strategy, as v3 does not support the CSS-based @theme syntax introduced in v4.
What happens if my token names contain invalid characters?
The TailwindV4EmitterHandler validates all token names against the regex /^[a-zA-Z0-9][a-zA-Z0-9-]*$/. If a token name contains spaces, special characters, or starts with a hyphen, the export exits with a non-zero status code and displays an error message indicating which token failed validation.
How do I import the generated CSS into a Tailwind v4 project?
Import the generated file into your main CSS entry point before the Tailwind directive. Tailwind v4 automatically scans imported CSS for @theme blocks and registers the custom properties as theme values:
@import './tailwind-theme.css';
@import 'tailwindcss';
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →