# How to Export DESIGN.md Tokens to Tailwind v3 JSON Format: A Complete Guide

> Export DESIGN.md tokens to Tailwind v3 JSON format using the google-labs-code/design.md CLI. Learn how to easily integrate design tokens into your tailwind.config.js file.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: how-to-guide
- Published: 2026-06-25

---

**The google-labs-code/design.md CLI converts DESIGN.md tokens into Tailwind v3-compatible JSON using the `json-tailwind` format option, which wraps the token mappings in a `{ "theme": { "extend": ... } }` structure for direct import into your [`tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/tailwind.config.js).**

The google-labs-code/design.md repository ships with a command-line tool that parses [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) files and validates their design tokens. When you need to export DESIGN.md tokens to Tailwind v3 JSON format, the CLI exposes a dedicated emitter that transforms the parsed design system state into a configuration object matching Tailwind's `theme.extend` schema.


## How the Export Pipeline Works

The export process follows a strict three-stage pipeline implemented in the CLI source code:

1. **Input Reading** – The `readInput` utility in [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts) accepts either a file path or stdin (`-`) and returns the raw content string.

2. **Linting and Parsing** – The `lint(content)` function processes the raw markdown, validates token definitions, and constructs a `DesignSystemState` object containing normalized groups for colors, typography, spacing, rounded corners, and other design primitives.

3. **Tailwind Emission** – When the format argument is `json-tailwind` (or its alias `tailwind`), the command instantiates a `TailwindEmitterHandler` from [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts). The handler's `execute(state)` method maps each token group to its corresponding Tailwind configuration key:
   - `colors` → color tokens
   - `fontFamily` and `fontSize` → typography definitions
   - `borderRadius` → rounded tokens
   - `spacing` → spacing units

The `TailwindEmitterHandler.execute(state)` function is a **pure function with no side effects**, meaning it returns a deterministic JSON object without modifying the input state or filesystem. The result is wrapped in `{ "theme": { "extend": ... } }` and serialized using `JSON.stringify(result.data, null, 2)` for pretty-printed output.


## CLI Command Syntax

Invoke the export command from the repository root using the CLI entry point defined in [`packages/cli/src/index.js`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/index.js):

```bash

# Using pnpm (recommended)

pnpm run cli export path/to/DESIGN.md json-tailwind > tailwind.tokens.json

# Using Node directly

node packages/cli/src/index.js export ./examples/totality-festival/DESIGN.md tailwind > tailwind.tokens.json

```

The command accepts two aliases for the format argument:
- `json-tailwind` (explicit)
- `tailwind` (shorthand)

If you provide an invalid format, the CLI exits with code 1 and writes a JSON error object to stderr (see [`export.ts`](https://github.com/google-labs-code/design.md/blob/main/export.ts) lines 44-48).

For stdin input, pass `-` as the file path:

```bash
cat DESIGN.md | node packages/cli/src/index.js export - json-tailwind

```


## Understanding the Tailwind v3 JSON Output Structure

The emitted JSON structure follows Tailwind v3's configuration schema exactly. Given a [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) file with this content:

```yaml
---
name: Example System
colors:
  primary: "#ff6f61"
  secondary: "#4a90e2"
typography:
  body:
    fontFamily: Inter
    fontSize: 16px
    lineHeight: 24px
    fontWeight: 400
rounded:
  sm: 4px
spacing:
  unit: 8px
---

```

The exporter generates:

```json
{
  "theme": {
    "extend": {
      "colors": {
        "primary": "#ff6f61",
        "secondary": "#4a90e2"
      },
      "fontFamily": {
        "body": ["Inter"]
      },
      "fontSize": {
        "body": ["16px", { "lineHeight": "24px", "fontWeight": "400" }]
      },
      "borderRadius": {
        "sm": "4px"
      },
      "spacing": {
        "unit": "8px"
      }
    }
  }
}

```

This structure allows Tailwind to generate utility classes like `text-primary`, `bg-secondary`, `font-body`, `rounded-sm`, and `mt-unit` based on your DESIGN.md definitions.


## Integrating with tailwind.config.js

Because the output is valid JSON wrapped in a `theme.extend` object, you can require it directly into your Tailwind configuration:

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: "class",
  theme: {
    extend: require("./tailwind.tokens.json").theme.extend,
  },
};

```

After running your build command (e.g., `npm run dev`), the following utility classes become available:
- `text-primary` maps to `#ff6f61`
- `bg-secondary` maps to `#4a90e2`
- `font-body` applies the Inter font family
- `rounded-sm` applies `4px` border radius
- `mt-unit` applies `8px` margin-top


## Key Source Files and Implementation Details

Understanding the underlying implementation helps when debugging or extending the export functionality:

- **[`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts)** – The CLI entry point that validates arguments, selects the appropriate emitter handler, and prints the formatted result to stdout.

- **[`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts)** – Contains the `TailwindEmitterHandler` class and its `execute(state)` method, which performs the actual mapping from `DesignSystemState` to Tailwind configuration keys.

- **[`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts)** – Provides the `readInput` helper that abstracts file system and stdin reading, enabling the export command to work with both physical files and piped input.

- **[`examples/totality-festival/tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/examples/totality-festival/tailwind.config.js)** – A working example in the repository demonstrating how to consume the emitted JSON in a real Tailwind v3 project.


## Summary

- The **google-labs-code/design.md** CLI provides native support for exporting to Tailwind v3 via the `json-tailwind` format argument.
- The export pipeline uses `TailwindEmitterHandler.execute(state)` in [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts) to convert parsed tokens into a `theme.extend` compatible structure.
- Output is wrapped in `{ "theme": { "extend": ... } }` and pretty-printed with 2-space indentation for direct consumption by [`tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/tailwind.config.js).
- The handler supports colors, typography (fontFamily, fontSize), borderRadius, and spacing tokens.
- Because the emitter is a pure function, you can safely redirect stdout to a file or pipe it to other tools without side effects.


## Frequently Asked Questions

### What Tailwind theme keys are supported when exporting DESIGN.md tokens?

The `TailwindEmitterHandler` maps four primary token categories to Tailwind configuration keys: `colors` for color tokens, `fontFamily` and `fontSize` for typography definitions, `borderRadius` for rounded tokens, and `spacing` for spacing units. Complex typography tokens automatically generate the tuple format required by Tailwind v3's `fontSize` configuration, including line-height and font-weight metadata.

### Can I use stdin instead of a file path for the export command?

Yes. The `readInput` utility in [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts) supports stdin input when you pass `-` as the file argument. This allows you to pipe DESIGN.md content directly into the CLI: `cat DESIGN.md | node packages/cli/src/index.js export - json-tailwind`.

### Does the CLI validate the DESIGN.md file before exporting?

Yes. The export command internally calls `lint(content)` to validate the DESIGN.md structure and build a `DesignSystemState` object. If validation fails, the CLI exits with code 1 and prints error details to stderr, preventing the generation of invalid Tailwind JSON.

### Is there a difference between the `json-tailwind` and `tailwind` format arguments?

No. According to the source in [`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts), `tailwind` is simply an alias for `json-tailwind`. Both arguments instantiate the same `TailwindEmitterHandler` and produce identical JSON output wrapped in the `theme.extend` structure.