# Design Token Aliases vs Canonical Token Names: Understanding the Difference in DESIGN.md

> Learn the difference between design token aliases and canonical token names. Understand how canonical names aid tooling and aliases improve ergonomics in DESIGN.md.

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

---

**Canonical token names are the authoritative identifiers used by tooling, while aliases are human-friendly alternatives that map to those canonical names for improved author ergonomics.**

The google-labs-code/design.md specification uses a dual-naming system to balance machine readability with human flexibility. Understanding the distinction between design token aliases and canonical token names is essential for writing valid DESIGN.md files that pass linting while remaining intuitive for authors.

## What Are Canonical Token Names?

**Canonical token names** are the primary, authoritative identifiers for sections or token groups within the DESIGN.md specification. These are the official identifiers used by the spec and by tooling when generating output. According to the source configuration in [`packages/cli/src/linter/spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.yaml) (lines 31-35), canonical names are defined under the `canonical` key and provide the single source of truth for validation and rendering.

When the linter checks section order or validates document structure, it always compares against these canonical names. The `CANONICAL_ORDER` constant in [`spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.ts) represents the definitive sequence that all DESIGN.md files must follow.

## What Are Design Token Aliases?

**Design token aliases** are alternative headings that the parser treats as equivalent to a canonical name. Aliases improve author ergonomics by allowing writers to use human-friendly or legacy phrasing without breaking validation. For example, an author can write `## Brand & Style` instead of `## Overview`, and the linter will treat both as the same section.

The alias mapping is defined in [`packages/cli/src/linter/spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.yaml) (lines 33-35) under the `aliases` array within each section definition. The `SECTION_ALIASES` map in [`spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.ts) (lines 52-57) stores these relationships, ensuring that each alias points to exactly one canonical name.

## How the Resolution System Works

The resolution system normalizes any heading—whether canonical or alias—to its canonical form before validation occurs.

### Configuration in spec-config.yaml

The YAML configuration establishes the relationship between canonical names and their aliases:

```yaml

# packages/cli/src/linter/spec-config.yaml

sections:
  - canonical: Overview
    aliases:
      - Brand & Style   # ← alias

  - canonical: Colors
  - canonical: Layout
    aliases:
      - Layout & Spacing

```

*Source:* [`packages/cli/src/linter/spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.yaml) lines 31-40.

### The resolveAlias Function

The `resolveAlias` function in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) (lines 59-62) handles the normalization:

```ts
import { resolveAlias } from '@google/design.md/linter/spec-config';

// Author wrote "Brand & Style" – we get the canonical name:
const heading = 'Brand & Style';
const canonical = resolveAlias(heading); // "Overview"

```

*Source:* [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) lines 59-62.

This function checks the `SECTION_ALIASES` map and returns the canonical equivalent. If the input is already a canonical name, it returns the input unchanged.

## Practical Usage in Linting

The normalization process is critical for the linter's section-order validation. In [`packages/cli/src/linter/linter/rules/section-order.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/linter/rules/section-order.ts) (line 34), the rule calls `resolveAlias` on every section heading before checking against `CANONICAL_ORDER`:

```ts
// packages/cli/src/linter/linter/rules/section-order.ts
import { resolveAlias, CANONICAL_ORDER } from '../../spec-config';

const normalized = sections.map(s => resolveAlias(s));
// Now `normalized` contains only canonical names for order checking.

```

When a DESIGN.md file contains the alias `## Brand & Style`, the linter calls `resolveAlias('Brand & Style')`, which returns `'Overview'`. The validation then treats the section as **Overview**, ensuring the canonical ordering rule validates correctly regardless of which alias the author chose.

## Code Examples

### Resolving an Alias to Canonical Form

```ts
import { resolveAlias } from '@google/design.md/linter/spec-config';

// Maps alias to canonical
const result = resolveAlias('Layout & Spacing'); // Returns "Layout"

```

*Source:* [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) lines 59-62.

### Configuring Aliases in YAML

```yaml

# packages/cli/src/linter/spec-config.yaml

sections:
  - canonical: Overview
    aliases:
      - Brand & Style
      - Introduction

```

*Source:* [`packages/cli/src/linter/spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.yaml) lines 31-35.

### Testing Alias Resolution

```ts
// packages/cli/src/linter/spec-config.test.ts
it('resolveAlias returns canonical for known alias', () => {
  const alias = 'Layout & Spacing';
  expect(resolveAlias(alias)).toBe('Layout');
});

```

*Source:* [`packages/cli/src/linter/spec-config.test.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.test.ts) lines 182-187.

## Summary

- **Canonical names** are the authoritative identifiers used by tooling and defined in [`spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/spec-config.yaml) under the `canonical` key.
- **Aliases** are human-friendly alternatives mapped to canonical names via the `aliases` array in the YAML configuration.
- The `resolveAlias` function in [`spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.ts) normalizes any heading to its canonical form before validation.
- The linter uses this normalization to validate section order in [`section-order.ts`](https://github.com/google-labs-code/design.md/blob/main/section-order.ts) without requiring authors to memorize exact canonical names.

## Frequently Asked Questions

### Can I use aliases interchangeably with canonical names?

Yes. The `resolveAlias` function treats both aliases and canonical names identically, returning the canonical form in either case. According to the implementation in [`spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.ts) (lines 59-62), if you pass a canonical name to `resolveAlias`, it returns the name unchanged; if you pass an alias, it returns the mapped canonical name.

### Where are canonical names and aliases defined?

They are defined in [`packages/cli/src/linter/spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.yaml) (lines 31-40). Each section entry contains a `canonical` field and an optional `aliases` array. The TypeScript loader in [`spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.ts) (lines 52-57) parses this YAML to create the `SECTION_ALIASES` mapping used at runtime.

### How does the linter handle unknown aliases?

The `resolveAlias` function returns the input string unchanged if it does not match a known alias or canonical name. In the section-order rule ([`section-order.ts`](https://github.com/google-labs-code/design.md/blob/main/section-order.ts), line 34), this results in the unknown heading failing validation against the `CANONICAL_ORDER` array, triggering a lint error.

### What happens if an alias conflicts with a canonical name?

The test suite in [`spec-config.test.ts`](https://github.com/google-labs-code/design.md/blob/main/spec-config.test.ts) (lines 182-187) ensures that aliases do not collide with canonical names during resolution. The configuration loader creates a bidirectional mapping where aliases always resolve to their declared canonical names, and canonical names resolve to themselves, preventing ambiguity in the lookup logic.