# How Design.md Handles Different Data Structures for Export

> Discover how Design.md exports diverse data structures like Tailwind JSON, CSS custom properties, and DTCG JSON using a strategy pattern and side-effect-free pipeline.

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

---

**The Design.md CLI employs a strategy pattern where format-specific emitter classes transform a common `DesignSystemState` model into distinct output structures—including Tailwind JSON, CSS custom properties, and DTCG-compliant JSON—through a pure, side-effect-free pipeline.**

The Design.md project from Google Labs provides a CLI tool that converts design-system tokens defined in [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) files into production-ready code. To handle different data structures for export, the architecture cleanly separates token modeling from format-specific serialization, enabling developers to add new output targets without modifying core logic.

## How the Export Pipeline Handles Different Data Structures

The export system orchestrates the conversion process through three distinct layers defined in [`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts) and supporting files.

### CLI Command Dispatch

The entry point validates the `--format` argument against a closed `FORMATS` enum, runs the linter to obtain a `DesignSystemState`, and dispatches to the appropriate handler. This ensures only supported data structures are generated and provides a unified interface for all export operations.

### The Format-Agnostic Model

At the core lies the `DesignSystemState` model defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts). This pure data structure stores tokens as `Map<string, …>` objects (e.g., `state.colors`, `state.typography`, `state.spacing`), remaining completely agnostic to output formats. Because the model contains no side effects, emitters can focus exclusively on mapping these maps to their target structures.

### Emitter Strategy Pattern

Each export format implements a specific emitter class conforming to the `*EmitterSpec` interface. These classes receive the `DesignSystemState` and return a standardized result object `{ success: boolean, data: … }`. This pattern isolates format-specific logic—such as JSON schema construction or CSS string building—within dedicated handlers.

## Supported Data Structures for Export

The CLI supports four distinct output structures, each handled by a specialized emitter class.

### Tailwind v3 (JSON Theme Extension)

The `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) converts tokens into a JSON object matching Tailwind’s `theme.extend` schema. It transforms color maps into `record<string, string>` hex values, typography into nested arrays of `[size, meta]`, and dimensions into plain strings like `"4rem"`.

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

```

Internally, the handler executes:

```typescript
const handler = new TailwindEmitterHandler();
const result = handler.execute(state);
// result.data = { theme: { extend: { colors: {...}, spacing: {...} } } }

```

### Tailwind v4 (CSS @theme Block)

For Tailwind v4, the `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) generates CSS custom properties wrapped in an `@theme` block. It builds a `TailwindV4ThemeData` object and serializes it via `serializeTailwindV4` from [`packages/cli/src/linter/tailwind/v4/serialize.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/v4/serialize.ts), producing names like `--color-primary` and `--spacing-lg`.

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

```

The serialization process converts the intermediate data structure into valid CSS:

```typescript
const handler = new TailwindV4EmitterHandler();
const result = handler.execute(state);
process.stdout.write(serializeTailwindV4(result.data.theme));

```

### CSS Custom Properties (Variable Declarations)

The `CssVarsEmitterHandler` in [`packages/cli/src/linter/css-vars/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/css-vars/handler.ts) flattens token names (converting dots to hyphens) and emits an array of `{ name, value }` declarations. The `serializeCssVars` helper then converts these into CSS custom property syntax. Users can prepend a custom prefix using the `--prefix` flag.

```bash
npx @google/design.md export --format css-vars --prefix my-app DESIGN.md > vars.css

```

This produces declarations like:

```css
--my-app-color-primary: #ff0000;

```

### W3C DTCG (Standard Token JSON)

The `DtcgEmitterHandler` in [`packages/cli/src/linter/dtcg/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/dtcg/handler.ts) maps tokens into the W3C Design Tokens Format (DTCG) schema. It adds required metadata fields including `$schema`, `$type`, and `$value`, producing JSON that validates against `https://www.designtokens.org/schemas/2025.10/format.json`.

```bash
npx @google/design.md export --format dtcg DESIGN.md > tokens.json

```

## Extending Support for Different Data Structures

Adding support for new export formats requires three steps:

1. Implement a new emitter class conforming to the `*EmitterSpec` interface that returns `{ success: boolean, data: … }`.
2. Register the format string in the `FORMATS` constant and add a dispatch branch in [`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts).
3. If the output isn't plain JSON, implement a serializer function (like `serializeTailwindV4` or `serializeCssVars`) to handle the final string conversion.

This architecture ensures that the core linting and modeling logic remains untouched when introducing new export targets.

## Summary

- The Design.md CLI handles different data structures for export through a strategy pattern using format-specific emitter classes.
- All emitters operate on a pure, side-effect-free `DesignSystemState` model defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts).
- Four built-in formats are supported: Tailwind v3 JSON, Tailwind v4 CSS, CSS custom properties, and W3C DTCG JSON.
- Each format has a dedicated handler: `TailwindEmitterHandler`, `TailwindV4EmitterHandler`, `CssVarsEmitterHandler`, and `DtcgEmitterHandler`.
- The system is extensible by implementing new emitters and registering them in the `FORMATS` enum and export command dispatcher.

## Frequently Asked Questions

### What data structure does the Design.md CLI use as the source of truth for exports?

The CLI uses the `DesignSystemState` model defined in [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts). This format-agnostic structure stores all tokens as `Map` objects (e.g., `state.colors`, `state.typography`), allowing emitters to transform the same underlying data into multiple output formats without duplication.

### How do I export Design.md tokens to Tailwind CSS v4 format?

Use the `css-tailwind` format flag: `npx @google/design.md export --format css-tailwind DESIGN.md`. The `TailwindV4EmitterHandler` processes the state into a `TailwindV4ThemeData` object, which `serializeTailwindV4` converts into a CSS `@theme` block containing custom properties like `--color-primary`.

### Can I add a custom prefix to CSS variable exports?

Yes. When using the `css-vars` format, include the `--prefix` flag: `npx @google/design.md export --format css-vars --prefix my-app DESIGN.md`. The `CssVarsEmitterHandler` prepends this prefix to every token name, generating variables like `--my-app-color-primary` instead of `--color-primary`.

### What is the DTCG export format and where is it implemented?

The DTCG (Design Tokens Community Group) format exports tokens as JSON conforming to the W3C Design Tokens Format specification. It is implemented in [`packages/cli/src/linter/dtcg/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/dtcg/handler.ts) by the `DtcgEmitterHandler` class, which structures output with `$schema`, `$type`, and `$value` fields required by the standard.