# What Validation Rules Does the `lint` Command Enforce in Design.md?

> Discover the 11 validation rules enforced by the Design.md lint command. Ensure structural integrity, token completeness, accessibility, and schema conformance for your DESIGN.md files.

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

---

**The `lint` command in the Design.md CLI enforces 11 built-in validation rules that check for structural integrity, token completeness, accessibility compliance, and schema conformance across your [`DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/DESIGN.md) files.**

The Design.md CLI provides a robust linting pipeline that parses your design system markdown, builds a typed model, and validates it against a strict rule set. Understanding the specific validation rules the `lint` command enforces helps you maintain consistent, accessible, and error-free design tokens before they reach production.

## Structural and Schema Validation

The linter first ensures your document structure follows the expected schema and contains all required sections.

### Unknown Key Detection

The **`unknown-key`** rule (implemented in [`packages/cli/src/linter/rules/unknown-key.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/rules/unknown-key.ts)) runs at the warning level to catch top-level YAML keys that appear to be typos of known schema keys. It computes the Levenshtein edit distance (maximum of 2) against the canonical `SCHEMA_KEYS` constant and suggests the closest valid match. The implementation uses a fast pre-filter on length difference before running the full `levenshtein()` algorithm to find the best match.

### Required Sections

The **`missing-sections`** rule validates that required top-level sections—such as `palette`, `typography`, and `tokens`—are present in the markdown document. It checks the `state.documentSections` array against a constant list of required headings and emits a warning if any are absent.

### Section Ordering

The **`section-order`** rule enforces conventional markdown organization by comparing the order of headings in `state.documentSections` against a predefined sequence (for example, ensuring `Palette` appears before `Tokens`). This rule runs at the info level and helps maintain consistent documentation structure across projects.

## Token Integrity and References

These rules validate that your design tokens are complete, correctly typed, and properly referenced throughout the system.

### Primary Token Requirement

The **`missing-primary`** rule (severity: error) ensures your design system defines a primary color or token required for generating a complete Tailwind theme. It scans `state.tokens` for the `primary` key and emits an error if absent, preventing incomplete palette generation.

### Typography Definitions

The **`missing-typography`** rule checks for missing typography definitions—including font-size, line-height, and related properties—that the schema expects. It scans `state.typography` for required sub-keys and reports any gaps at the warning level.

### Type Validation

The **`types`** rule (severity: error) validates that token values match their declared types in the schema—such as ensuring color strings follow valid formats and numeric sizes contain numbers. It checks each token against its `type` field and reports mismatches that could break downstream consumption.

### Reference Integrity

The **`broken-ref`** rule detects YAML references (`$ref`) that point to non-existent tokens or sections. It walks the reference graph and reports dangling pointers at the error level, preventing broken dependencies in your design system.

### Orphaned Tokens

The **`orphaned-tokens`** rule identifies tokens defined but never referenced elsewhere in the system. It traverses the token graph and reports any nodes with zero inbound edges as warnings, helping you eliminate unused variables that clutter the codebase.

### Token Typo Detection

The **`token-like-ignored`** rule applies the same Levenshtein-distance heuristic as `unknown-key` but specifically to token names. It warns when a token appears to be a typo of a known token (for example, `--primary-colr` instead of `--primary-color`), catching misspellings before they propagate.

## Accessibility and Quality Checks

### WCAG Contrast Compliance

The **`contrast-ratio`** rule (severity: error) validates WCAG contrast ratios between foreground and background color pairs. It computes relative luminance and flags combinations that fall below accessibility thresholds—4.5:1 for normal text and 3:1 for large text—ensuring your design system meets accessibility standards.

### Token Summary Reporting

The **`token-summary`** rule provides a high-level informational report of token counts per category (color, spacing, typography, etc.). It aggregates token keys by prefix and emits a summary finding for quick sanity-checking of your design system's scope.

## How the Linter Executes Rules

When you invoke the `lint` command, the pipeline defined in [`packages/cli/src/linter/lint.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/lint.ts) executes three phases:

1. **Parsing**: The `ParserHandler` converts the markdown into an AST.
2. **Model Building**: The `ModelHandler` resolves tokens into a strongly-typed `DesignSystemState`.
3. **Rule Execution**: The `runLinter` function (from [`packages/cli/src/linter/runner.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/runner.ts)) loads the `DEFAULT_RULES` array and executes each rule against the state, collecting `Finding` objects.

The runner aggregates findings by severity (error, warning, info) and returns a `LintReport` that the CLI formats for display.

## Running the Linter

### Command Line Usage

Execute the linter against your design document:

```bash

# From the repository root

npm install
npx design-md lint path/to/DESIGN.md

```

The command outputs a severity summary and specific findings:

```

✖ 3 errors, ⚠ 5 warnings, ℹ 2 infos
  - unknown-key: "colou" – did you mean "color"?
  - contrast-ratio: "primary" vs "background" contrast 2.9:1 (needs ≥ 4.5:1)
  - missing-primary: primary colour not defined

```

### Programmatic API

Import the `lint` function to validate design systems in code:

```typescript
import { lint } from '@design-md/cli';

const designMd = await readFile('DESIGN.md', 'utf-8');
const report = lint(designMd);

if (report.summary.errors) {
  console.error('Design system has errors – fix them before publishing.');
}

```

### Custom Rule Injection

Override the default rule set by passing custom rules via `LintOptions`:

```typescript
import { lint, LintOptions, LintRule } from '@design-md/cli';

const myRule: LintRule = {
  name: 'my-custom-rule',
  severity: 'info',
  description: 'Example of a custom rule.',
  run: (state) => [{ path: 'custom', message: 'All good!' }],
};

const opts: LintOptions = { rules: [myRule] };
const report = lint(designMd, opts);

```

## Summary

- The Design.md CLI `lint` command enforces 11 distinct validation rules located in `packages/cli/src/linter/rules/`.
- Rules cover four domains: **structural validation** (unknown keys, section order), **token integrity** (missing primary, broken refs, orphaned tokens), **accessibility** (contrast ratios), and **quality reporting** (token summaries).
- Severities range from error (blocking) to info (advisory), with critical issues like missing primary colors or failed contrast ratios preventing successful validation.
- The linting pipeline runs through [`packages/cli/src/linter/lint.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/lint.ts), which coordinates parsing, model building, and rule execution via `runLinter` and `DEFAULT_RULES`.
- You can extend or override the default rule set programmatically using the `LintOptions.rules` array.

## Frequently Asked Questions

### How does the contrast-ratio rule calculate accessibility compliance?

The **`contrast-ratio`** rule computes the relative luminance of foreground and background color pairs according to WCAG 2.1 specifications. It validates that normal text meets a 4.5:1 contrast ratio and large text meets a 3:1 ratio, emitting an error for any pair that falls below these thresholds.

### Can I disable specific validation rules?

Yes. While the CLI uses `DEFAULT_RULES` from [`packages/cli/src/linter/runner.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/runner.ts) by default, you can override the rule set programmatically by providing a custom `rules` array in the `LintOptions` parameter when calling the `lint` function directly.

### What happens if I misspell a top-level YAML key?

The **`unknown-key`** rule detects likely misspellings by calculating the Levenshtein distance between your key and known schema keys. If the distance is 2 or less, it suggests the closest valid key, helping you catch typos like `colou` instead of `color` before they cause parsing failures.

### Does the linter check for unused design tokens?

Yes. The **`orphaned-tokens`** rule traverses the token reference graph and reports any tokens with zero inbound references. This identifies defined variables that are never consumed, allowing you to clean up dead code from your design system.