# How the Export Functionality Works in design.md: From DESIGN.md to Tailwind, DTCG, and CSS Variables

> Learn how the design.md export functionality transforms DESIGN.md into Tailwind CSS, W3C Design Tokens, and CSS variables. Explore the pure, functional pipeline and emitter handlers today.

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

---

**The export functionality in the google-labs-code/design.md repository (Instagit) converts DESIGN.md files into Tailwind v3 JSON, Tailwind v4 CSS, W3C Design Tokens, or CSS custom properties through a pure, functional pipeline that parses CLI arguments, lints the input, and routes to specific emitter handlers.**

This export functionality lives entirely within the CLI package and follows a strict sequence: input validation, file reading, linting into a `DesignSystemState`, format-specific emission, and final serialization to stdout.

## Command-Line Parsing and Validation

The export entry point is defined in [`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts) using the `citty` command framework. The command accepts three arguments:

- `file` – Path to the DESIGN.md file, or `-` to read from stdin
- `format` – One of five supported export formats: `css-tailwind`, `json-tailwind`, `tailwind`, `dtcg`, or `css-vars`
- `prefix` – Optional CSS variable prefix (used only with `css-vars` format)

Validation occurs against a closed enum. If the provided format is invalid, the CLI immediately writes a JSON error payload to stderr and exits with status code 1:

```typescript
// packages/cli/src/commands/export.ts (lines 49-57)
if (!FORMATS.includes(format as ExportFormat)) {
  console.error(JSON.stringify({
    error: 'INVALID_FORMAT',
    message: `Invalid format "${format}". Valid formats: ${FORMATS.join(', ')}`,
  }));
  process.exitCode = 1;
  return;
}

```

## Input Reading and Error Handling

Before processing begins, the `readInput` function from [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts) loads the source content. This utility handles both file system access and stdin streams, wrapping I/O errors in a `FileReadError` that triggers exit code 2 and produces a user-friendly JSON error message.

## The Linting Step: Parsing DESIGN.md

Every export operation begins with linting. The raw markdown text is passed to the `lint` function exported from [`packages/cli/src/linter/index.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/index.ts). This step parses the DESIGN.md into a `DesignSystemState` object and validates the content against design system rules.

The linting step is **mandatory** and **always executed** because all emitters require the parsed `DesignSystemState` object as their input. Even when the lint step produces warnings, the export continues unless critical errors prevent state generation.

## Export Format Handlers

After successful linting, the CLI instantiates a specific emitter handler based on the `--format` flag. Each handler implements an `execute(state)` method that maps the `DesignSystemState` to the target format through pure, side-effect-free transformations.

### Tailwind v3 JSON Output

The `TailwindEmitterHandler` (located at [`packages/cli/src/linter/tailwind/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/tailwind/handler.ts)) generates a Tailwind v3 compatible `theme.extend` configuration object:

```typescript
// Tailwind v3 emitter (excerpt, lines 24-35)
return {
  success: true,
  data: {
    theme: {
      extend: {
        colors: this.mapColors(state),
        fontFamily: this.mapFontFamilies(state),
        fontSize: this.mapFontSizes(state),
        borderRadius: this.mapDimensions(state.rounded),
        spacing: this.mapDimensions(state.spacing),
      },
    },
  },
};

```

This output is suitable for extending a [`tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/tailwind.config.js) file.

### Tailwind v4 CSS Output

The `TailwindV4EmitterHandler` ([`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)) produces CSS for Tailwind v4's `@layer theme` syntax. This handler includes strict validation: every token name is verified against the CSS identifier regex `/^[a-zA-Z0-9][a-zA-Z0-9-]*$/`. If any token name fails validation, the emitter returns `success: false` with an `INVALID_TOKEN_NAME` error, causing the CLI to exit with status 1.

### W3C Design Tokens (DTCG)

The `DtcgEmitterHandler` ([`packages/cli/src/linter/dtcg/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/dtcg/handler.ts)) converts the design system into the W3C Design Tokens Community Group format. This produces a standardized JSON payload that interoperates with design token management tools and other design system platforms.

### CSS Custom Properties

The `CssVarsEmitterHandler` ([`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)) outputs CSS custom properties (variables) using the optional `--prefix` flag. Tokens are serialized as `--${prefix}var: value;` declarations, making them immediately usable in modern CSS workflows.

## Serialization and Output Generation

After the emitter handler executes successfully, the CLI serializes the result for stdout:

- **JSON formats** (`json-tailwind`, `tailwind`, `dtcg`) are pretty-printed using `JSON.stringify(data, null, 2)`
- **CSS formats** (`css-tailwind`, `css-vars`) use specialized serializers: `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)) and `serializeCssVars` (from [`packages/cli/src/linter/css-vars/serializer.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/css-vars/serializer.ts))

The entire pipeline remains pure until the final write operation, printing the formatted string to stdout or writing error details to stderr.

## Exit Codes and Error Behavior

The export functionality uses specific exit codes to signal operation status:

- **Exit code 0**: Successful export, even if linting generated warnings
- **Exit code 1**: Invalid format selection, emitter validation failure (such as invalid Tailwind v4 token names), or other processing errors
- **Exit code 2**: File read errors (I/O failures when loading the DESIGN.md source)

## Practical Usage Examples

Export to Tailwind v3 configuration:

```bash
instagit export ./examples/totality-festival/DESIGN.md json-tailwind > tailwind-theme.json

```

Generate Tailwind v4 CSS:

```bash
instagit export ./examples/paws-and-paths/DESIGN.md css-tailwind > tailwind-v4.css

```

Create W3C Design Tokens:

```bash
instagit export ./examples/atmospheric-glass/DESIGN.md dtcg > design-tokens.json

```

Export CSS variables with custom prefix:

```bash
instagit export ./examples/totality-festival/DESIGN.md css-vars --prefix="my-app"

# Output: --my-app-color-primary: #ff5722;

```

## Summary

- The export functionality in [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) converts DESIGN.md files into Tailwind v3, Tailwind v4, DTCG, or CSS variable formats through a pipeline defined in [`packages/cli/src/commands/export.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/commands/export.ts).
- The process requires three steps: command-line validation using `citty`, input reading via `readInput`, and mandatory linting to produce a `DesignSystemState` object.
- Four emitter handlers (`TailwindEmitterHandler`, `TailwindV4EmitterHandler`, `DtcgEmitterHandler`, `CssVarsEmitterHandler`) transform the parsed state into format-specific outputs using pure mapping functions.
- Tailwind v4 output validates token names against CSS identifier requirements, returning `INVALID_TOKEN_NAME` errors for non-compliant names.
- Exit codes distinguish between success (0), processing errors (1), and file I/O failures (2), with all errors written as JSON to stderr.

## Frequently Asked Questions

### What file formats can the export functionality generate?

The export functionality supports five specific formats: `css-tailwind` (Tailwind v4 CSS), `json-tailwind` or `tailwind` (Tailwind v3 JSON), `dtcg` (W3C Design Tokens), and `css-vars` (CSS custom properties). Each format is handled by a dedicated emitter class in the `packages/cli/src/linter/` directory that transforms the parsed `DesignSystemState` into the target specification.

### Why is the linting step mandatory for all exports?

The linting step is mandatory because every emitter handler requires a validated `DesignSystemState` object as input. Located in [`packages/cli/src/linter/index.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/index.ts), the `lint` function parses the raw DESIGN.md markdown and constructs the state object that maps design tokens to the specific requirements of each export format. Without this parsing step, the emitters cannot access structured token data.

### How does the export functionality handle invalid token names?

For Tailwind v4 CSS output, the `TailwindV4EmitterHandler` validates every token name against the regex `/^[a-zA-Z0-9][a-zA-Z0-9-]*$/` to ensure CSS identifier compliance. If any token name contains invalid characters, the emitter returns `success: false` with an `INVALID_TOKEN_NAME` error, causing the CLI to exit with status code 1 and write a JSON error object to stderr.

### What is the difference between the Tailwind v3 and v4 export handlers?

The `TailwindEmitterHandler` generates a JSON configuration object suitable for [`tailwind.config.js`](https://github.com/google-labs-code/design.md/blob/main/tailwind.config.js) files, nesting values under `theme.extend`. The `TailwindV4EmitterHandler` produces raw CSS using the `@layer theme` syntax and includes additional validation for CSS identifier compatibility. While the v3 handler outputs configuration objects, the v4 handler outputs directly usable CSS rules.