How to Extend DESIGN.md with Custom YAML Keys: A Complete Guide

You can add any top-level YAML key to DESIGN.md as a custom extension, and the linter will ignore keys that are not close matches to schema fields while preserving them for downstream tools.

The google-labs-code/design.md repository defines a token schema that is intentionally extensible. While the specification governs standard keys like colors and typography, the parser and linter accept arbitrary top-level YAML keys without breaking validation. This architecture allows design systems to store metadata, branding guidelines, or integration-specific data alongside official design tokens.

How Custom YAML Keys Work in DESIGN.md

The extension mechanism relies on three core components that distinguish between schema violations and intentional custom data.

Permissive YAML Parsing

In packages/cli/src/linter/spec-config.ts, the front-matter loader uses a permissive YAML parser that produces a plain JavaScript object. Unlike strict schemas that reject unknown properties, this parser accepts any syntactically valid YAML key as a top-level property, loading the entire front matter into a generic object that preserves custom extensions.

The Unknown-Key Lint Rule

The unknown-key rule in packages/cli/src/linter/linter/rules/unknown-key.ts implements intelligent typo detection using Levenshtein distance calculations. When the linter encounters a key not defined in the official schema, it computes the edit distance between the unknown key and all known schema keys. If the distance falls below a configurable threshold, the linter warns of a probable typo. Keys with distances above the threshold are treated as custom extensions and generate no findings.

Consumer Behavior for Unknown Content

According to docs/spec.md, the Consumer Behavior for Unknown Content section mandates that tools must accept unknown keys provided their values are syntactically valid. When consuming DESIGN.md files, the CLI and other tools copy these custom keys through unchanged, enabling round-tripping and allowing specialized agents to read the additional data.

Adding Custom YAML Keys to Your DESIGN.md

To extend your design tokens with custom metadata, add any valid YAML key at the top level of your front matter. Choose names that are distinct from standard schema keys to avoid typo warnings.

---
name: Aurora
colors:
  primary: "#1A1C1E"
  secondary: "#6C7278"
typography:
  body-md:
    fontFamily: Public Sans
    fontSize: 1rem

# Custom extension - preserved but ignored by standard linting

branding:
  logo: "./assets/logo.svg"
  tagline: "Bright ideas, bold design"
---

The branding key above is not part of the official DESIGN.md schema, but it remains valid. The linter will not flag it because "branding" is sufficiently different from known keys like colors or name.

Accessing Custom Keys Programmatically

When parsing DESIGN.md files in your own tools, the custom keys appear in the parsed front matter object alongside standard properties.

import { parseDesignMd } from '@google/design.md/parser';

const markdown = await Deno.readTextFile('DESIGN.md');
const { frontMatter } = parseDesignMd(markdown);

// Access custom extension data
console.log(frontMatter.branding?.logo);   // → "./assets/logo.svg"
console.log(frontMatter.branding?.tagline); // → "Bright ideas, bold design"

Because the parser in spec-config.ts loads the YAML into a generic object without filtering unknown properties, your custom data remains accessible throughout the pipeline.

Validating DESIGN.md Files with Custom Extensions

Run the linter to verify that your custom keys do not trigger warnings:

npx @google/design.md lint DESIGN.md

# Exits with code 0 - no warnings for custom keys

If you accidentally use a key close to a standard one, such as colours instead of colors, the unknown-key rule will emit a warning suggesting the correction. To silence this, either correct the spelling or choose a more distinct custom key name like brandColors or customColours.

Summary

  • Add any top-level key to DESIGN.md front matter to store custom metadata alongside design tokens.
  • The permissive parser in packages/cli/src/linter/spec-config.ts loads all YAML keys into a generic object without filtering.
  • The unknown-key rule uses Levenshtein distance to distinguish between typos and intentional custom extensions.
  • Consumer behavior mandates that unknown keys are preserved during export and round-tripping, making them available to downstream tools.
  • Choose distinct names for custom keys to avoid triggering typo warnings from the linter.

Frequently Asked Questions

Will custom YAML keys break the DESIGN.md linter?

No. The linter explicitly tolerates unknown keys that are not close matches to schema fields. As implemented in packages/cli/src/linter/linter/rules/unknown-key.ts, the rule only warns when an unknown key appears to be a misspelling of a known property. Truly custom keys with distinct names pass validation silently.

How do I prevent the linter from flagging my custom key as a typo?

Ensure your custom key name has a Levenshtein distance greater than the configurable threshold from all standard schema keys. For example, use brandMetadata instead of color or colour. If the linter suggests a correction, your key name is too similar to an existing schema field.

Are custom keys preserved when exporting design tokens?

Yes. According to the consumer behavior specification in docs/spec.md, tools must copy unknown keys through unchanged during export operations. This guarantees round-tripping and allows external pipelines to access custom metadata stored in the DESIGN.md file.

Can I add custom keys at nested levels within standard schema objects?

The extension mechanism primarily targets top-level keys. While the permissive YAML parser may preserve nested unknown properties, the unknown-key rule and consumer behavior guarantees focus on top-level extensions. For maximum compatibility with DESIGN.md tooling, place custom keys at the root level of your YAML front matter.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →