# Best Practices for Using the Export Feature in Design.md: A Complete Guide

> Master Design.md export best practices. Convert token definitions to Tailwind v3 JSON, v4 CSS, or W3C DTCG for deterministic design system pipelines.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: best-practices
- Published: 2026-07-02

---

**The export feature in Design.md converts token definitions from DESIGN.md files into Tailwind v3 JSON, Tailwind v4 CSS, or W3C DTCG format using pure emitter handlers located in the CLI package, enabling deterministic design system pipelines when integrated with linting and CI workflows.**

The `export` feature in the [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) repository provides a robust mechanism for transforming markdown-based design tokens into implementation-ready code. By leveraging side-effect-free emitter functions and standardized exit codes, this tool bridges the gap between design specifications and development workflows. Understanding the internal architecture ensures reliable automation and extensibility for custom design system needs.

## Understanding the Export Architecture

The export pipeline follows a strict functional architecture that separates parsing, transformation, and serialization concerns. This design ensures testability and consistent behavior across different output formats.

### CLI Entry Point and Emitter Selection

The export command begins at the CLI entry point in [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts), which handles generic I/O utilities and argument parsing. Based on the `--format` flag, the dispatcher routes to one of three specialized handlers:

- **Tailwind v3** → `TailwindEmitterHandler` 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)
- **Tailwind v4** → `TailwindV4EmitterHandler` in [`packages/cli/src/linter/tailwind/v4/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/v4/handler.ts)
- **W3C DTCG** → `DTCGEmitterHandler` (located alongside other emitters in the linter directory)

### Pure Mapping Functions

Each emitter receives a fully parsed `DesignSystemState` object and returns a plain JavaScript object through a pure `execute(state)` method. The `TailwindEmitterHandler` constructs the `theme.extend` structure by invoking specialized mapping functions:

- `mapColors` generates `{ name: hex }` objects for color tokens
- `mapFontFamilies` produces `{ name: [family] }` arrays for typography
- `mapDimensions` and `dimToString` handle font sizes, border-radius, and spacing values

These functions are side-effect-free, making them easy to unit test and compose into custom pipelines.

### Serialization and Exit-Codes

The raw emitter output passes through `formatOutput` in [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts), which serializes JSON with pretty-printing or generates CSS blocks. The CLI adheres to a strict exit-code contract for CI integration:

- `0` indicates successful export
- `1` signals an invalid `--format` argument or emitter error
- `2` indicates the input DESIGN.md file cannot be read

## Export Format Options

The export feature supports three primary output formats, each serving distinct integration scenarios.

### json-tailwind (Alias: tailwind)

Generates a JSON object intended for `theme.extend` in Tailwind v3 configurations. This format produces a ready-to-paste fragment for [`tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/tailwind.config.js), mapping tokens to Tailwind's theme structure.

### css-tailwind

Outputs a CSS `@theme { … }` block using Tailwind v4 custom-property namespaces. This format creates a standalone CSS file that Tailwind v4 can consume directly without additional JavaScript configuration.

### dtcg

Produces Design Token JSON conforming to the W3C Design Tokens Community Group (DTCG) specification. This format enables interoperability with other design-token tools and platforms that support the standardized schema.

## Recommended Usage Patterns

### One-Off Token Generation

For manual updates, pipe the output directly to a version-controlled file:

```bash
npx @google/design.md export --format json-tailwind DESIGN.md > tailwind.theme.json

```

Store the generated file in your repository to ensure reproducible builds across environments.

### CI Lint-Then-Export Pipeline

Always run the linter before exporting to catch token errors early:

```bash
npx @google/design.md lint DESIGN.md && npx @google/design.md export --format css-tailwind DESIGN.md > theme.css

```

While the exporter succeeds even if linting finds warnings, CI jobs should enforce a clean lint pass to prevent invalid tokens from reaching production.

### Programmatic Integration

Import the library directly for custom tooling:

```typescript
import { exportDesign } from '@google/design.md/cli';
import { parse } from '@google/design.md/parser';

const { designSystem } = parse(markdown);
const result = exportDesign(designSystem, 'json-tailwind');

```

This approach uses the same pure handlers as the CLI while allowing custom pre-processing or post-processing of the `DesignSystemState`.

### Debugging Output

Use the markdown format to inspect the emitter's raw object structure:

```bash
npx @google/design.md export --format markdown DESIGN.md

```

This human-readable dump helps verify token mappings before committing to a specific output format.

## Implementation Examples

### Exporting Tailwind v3 JSON from a Script

The following TypeScript example demonstrates programmatic usage without the CLI:

```typescript
import { readFileSync } from 'node:fs';
import { parse } from '@google/design.md/parser';
import { TailwindEmitterHandler } from '@google/design.md/packages/cli/src/linter/tailwind/handler';
import { formatOutput } from '@google/design.md/packages/cli/src/utils';

// Load and parse DESIGN.md
const markdown = readFileSync('DESIGN.md', 'utf-8');
const { designSystem } = parse(markdown);

// Run the Tailwind v3 emitter
const emitter = new TailwindEmitterHandler();
const result = emitter.execute(designSystem);

// Serialize as pretty-printed JSON
const json = formatOutput(result.data, { format: 'json' });
console.log(json);

```

### GitHub Actions CI Workflow

Automate token generation in a CI pipeline using the exit-code contract:

```yaml
name: Export Design Tokens
on: [push]
jobs:
  export:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install dependencies
        run: npm ci
      - name: Lint DESIGN.md
        run: npx @google/design.md lint DESIGN.md
      - name: Export Tailwind v4 CSS
        run: |
          npx @google/design.md export --format css-tailwind DESIGN.md > theme.css
      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: tailwind-theme
          path: theme.css

```

The job fails automatically if either linting or exporting returns a non-zero exit code.

### Creating a Custom Emitter

Extend the system by implementing the `EmitterSpec` interface:

```typescript
// src/linter/custom/custom-emitter.ts
export class MyCustomEmitter implements EmitterSpec {
  execute(state: DesignSystemState) {
    // Example: flatten all token names into a CSV string
    const rows = Array.from(state.colors.entries())
      .map(([name, color]) => `${name},${color.hex}`);
    return { success: true, data: rows.join('\n') };
  }
}

```

Register the emitter in the CLI's format switch and follow the existing handler pattern of returning `{ success: true, data: ... }` for consistency with `TailwindEmitterHandler`.

## Summary

- **Run `lint` before `export`** to catch token errors early and enforce quality gates.
- **Choose the appropriate format** (`json-tailwind`, `css-tailwind`, or `dtcg`) based on your target platform and Tailwind version.
- **Use exit codes** (`0`, `1`, `2`) in CI scripts to automate quality checks and artifact generation.
- **Leverage pure functions** 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) for programmatic access and testing.
- **Extend via EmitterSpec** by copying the pattern from existing handlers like `TailwindV4EmitterHandler`.

## Frequently Asked Questions

### What is the difference between json-tailwind and css-tailwind formats?

The `json-tailwind` format generates a JSON object for Tailwind v3's `theme.extend` configuration, while `css-tailwind` produces a CSS `@theme` block using Tailwind v4's custom-property syntax. Choose `json-tailwind` for JavaScript-based configuration files and `css-tailwind` for CSS-first Tailwind v4 setups.

### How do I handle export failures in CI pipelines?

The CLI returns specific exit codes: `1` for invalid format arguments or emitter errors, and `2` for file read errors. Structure your CI scripts to fail fast on non-zero codes, and always run `npx @google/design.md lint` before exporting to catch token definition errors before they reach the export stage.

### Can I use the export feature programmatically without the CLI?

Yes, import `exportDesign` from `@google/design.md/cli` or instantiate specific handlers like `TailwindEmitterHandler` directly 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). Both approaches accept a `DesignSystemState` object and return a structured result, allowing integration into custom build tools or preprocessors.

### Where are the emitter implementations located in the source code?

The Tailwind v3 emitter resides 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) as the `TailwindEmitterHandler` class, while the Tailwind v4 implementation is in [`packages/cli/src/linter/tailwind/v4/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/v4/handler.ts) as `TailwindV4EmitterHandler`. The DTCG emitter follows the same pattern in the adjacent directory structure. All emitters implement the `EmitterSpec` interface with a pure `execute(state)` method.