# DesignSystemState Data Structure: Internal Design System Representation in Instagit

> Explore the DesignSystemState data structure, Instagit's internal representation for tokens, components, and metadata. Learn how it enables fast lookup in the Instagit CLI.

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

---

**The `DesignSystemState` interface represents a fully-resolved design system in the Instagit CLI, storing tokens, components, and metadata in `Map` collections for fast lookup after YAML parsing and validation.**

The `DesignSystemState` data structure serves as the central source of truth throughout the Instagit design system pipeline. Defined in the CLI model layer within the google-labs-code/design.md repository, this interface captures all resolved design tokens—including colors, typography, spacing, and component definitions—after the parser and validator have processed the raw YAML. Understanding this internal structure is essential for developers extending the linter, building exporters, or writing test utilities.

## Core Properties of DesignSystemState

According to the source code 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), the `DesignSystemState` interface contains several typed properties that organize design data into fast-lookup `Map` collections.

### Token Collections

The primary token categories are stored as `Map` instances for O(1) access:

- **`colors`**: `Map<string, ResolvedColor>` — Maps token names to resolved RGBA values with luminance calculations.
- **`typography`**: `Map<string, ResolvedTypography>` — Maps token names to resolved font families, sizes, weights, and line heights.
- **`rounded`**: `Map<string, ResolvedDimension>` — Maps token names to border-radius dimensions.
- **`spacing`**: `Map<string, ResolvedDimension>` — Maps token names to spacing dimensions.

Each `Resolved*` type conveys the exact shape of the token after model validation, including computed values like WCAG luminance for colors.

### Component Definitions

The **`components`** property stores a `Map<string, ComponentDef>` that associates component names with their definitions. Unlike primitive tokens, components maintain their own property maps and track unresolved references.

### Symbol Table and Metadata

Auxiliary lookup mechanisms support the design system:

- **`symbolTable`**: `Map<string, ResolvedValue>` — Provides flat dot-notation lookups (e.g., `colors.primary`) returning any resolved primitive value.
- **`sections`**: `string[] | undefined` — Lists Markdown heading names discovered in the source file.
- **`unknownKeys`** and **`unknownKeyValues`**: Track unrecognized YAML keys and their raw values for round-tripping purposes.

Optional metadata fields include **`name`** and **`description`** for human-readable identification.

## The ComponentDef Sub-Structure

Defined in the same file ([`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts) lines 89-94), the **`ComponentDef`** interface represents individual component instances within the state:

```ts
export interface ComponentDef {
  properties: Map<string, ResolvedValue>;
  /** Unresolved references that failed to resolve */
  unresolvedRefs: string[];
}

```

The `properties` map stores component-specific token overrides, while `unresolvedRefs` captures reference strings that failed to resolve during the validation phase, enabling partial design systems to pass validation while flagging missing dependencies.

## Building and Using DesignSystemState

The state is constructed by the model handler in [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts), which transforms the raw `ParsedDesignSystem` into a fully resolved `DesignSystemState` after validation.

### Manual Construction

For tests or custom scripts, you can instantiate `DesignSystemState` directly:

```ts
import { DesignSystemState } from './linter/model/spec.js';
import { ResolvedColor, ResolvedDimension } from './linter/model/spec.js';

// Helper to build a ResolvedColor
function mkColor(hex: string): ResolvedColor {
  // In practice you would call the real parser; here we mock the fields.
  return {
    type: 'color',
    hex,
    r: parseInt(hex.slice(1, 3), 16),
    g: parseInt(hex.slice(3, 5), 16),
    b: parseInt(hex.slice(5, 7), 16),
    luminance: 0, // omitted for brevity
  };
}

// Minimal state with a single color token
const state: DesignSystemState = {
  name: 'Demo System',
  colors: new Map([['primary', mkColor('#ff0000')]]),
  typography: new Map(),
  rounded: new Map(),
  spacing: new Map(),
  components: new Map(),
  symbolTable: new Map([['colors.primary', mkColor('#ff0000')]]),
};

```

### Test Helper Utilities

The repository provides a `buildState` helper in [`packages/cli/src/linter/linter/rules/test-helpers.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/test-helpers.ts) (lines 17-25) that generates a fully resolved state from simple overrides:

```ts
import { buildState } from './linter/linter/rules/test-helpers.js';

// Override only the colors you care about
const state = buildState({
  colors: { primary: '#ff0000', accent: '#00ff00' },
  typography: { body: { fontFamily: 'Inter', fontSize: '1rem' } },
});

```

This utility runs the model handler, resolves references, and returns a ready-to-use `DesignSystemState` without manual `Map` construction.

### Serialization

To convert the `Map`-based state into plain JSON for output or storage, use the `serializeDesignSystemState` function from [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts) (lines 144-151):

```ts
import { serializeDesignSystemState } from './utils.js';

const json = serializeDesignSystemState(state);
console.log(JSON.stringify(json, null, 2));

```

This function recursively converts `Map` instances into plain objects suitable for JSON emission while preserving the semantic structure of the design system.

## Integration with the Model Handler

The `DesignSystemState` is not created in isolation. According to the implementation in [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts), the model handler processes the `ParsedDesignSystem`—the raw AST representation—through validation and resolution phases. The handler populates the `Map` collections, resolves token references, calculates derived values like color luminance, and ultimately produces the immutable state object passed to linters, exporters, and other downstream pipelines.

## Summary

- **`DesignSystemState`** is the core interface 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) representing a fully resolved design system after YAML parsing.
- Token categories (colors, typography, spacing, rounded) are stored as **`Map<string, Resolved*>`** for fast lookup.
- **Components** are stored as `Map<string, ComponentDef>` with their own properties and unresolved reference tracking.
- The **`symbolTable`** enables dot-notation lookups like `colors.primary` across all token types.
- Use **`buildState`** from test helpers for quick state generation in tests, or **`serializeDesignSystemState`** from [`utils.ts`](https://github.com/google-labs-code/design.md/blob/main/utils.ts) for JSON output.

## Frequently Asked Questions

### What is the difference between DesignSystemState and ParsedDesignSystem?

`ParsedDesignSystem` represents the raw AST output immediately after YAML parsing, containing potentially unresolved references and unvalidated values. `DesignSystemState` represents the fully resolved and validated state after the model handler has processed the parsed data, computed derived values like luminance, and populated the `Map` collections. The state is the authoritative source passed to downstream tools.

### How does the symbolTable property work?

The `symbolTable` property in `DesignSystemState` is a flat `Map<string, ResolvedValue>` that provides dot-notation access to any resolved token in the system. For example, accessing `symbolTable.get('colors.primary')` returns the same `ResolvedColor` instance stored in the `colors` map, enabling unified lookup across all token categories without knowing the specific token type in advance.

### Why are token collections stored as Map instead of plain objects?

The `DesignSystemState` uses `Map` collections rather than plain objects for token storage to guarantee O(1) lookup performance and preserve insertion order, which is critical for the linter and exporter pipelines processing large design systems. Additionally, `Map` supports any string key (including those that might conflict with object prototype properties) and provides a cleaner iteration API for the downstream processing logic in the CLI handlers.

### Where is DesignSystemState defined in the source code?

The `DesignSystemState` interface is 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) at lines 71-78, alongside the `ComponentDef` interface (lines 89-94) and various `Resolved*` token type definitions. The construction logic resides in [`packages/cli/src/linter/model/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/handler.ts), while serialization utilities are found in [`packages/cli/src/utils.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/utils.ts).