DESIGN.md import¶
pulp import-design --from designmd reads Google's
DESIGN.md format (Apache-2.0) — a
YAML-frontmatter + Markdown-body description of a design system — and
emits a W3C Design Tokens Community Group (DTCG) tokens.json. The
upstream spec is the source of truth for the format; this page documents
the Pulp parser, its detection rules, and the Phase 1 contract.
Because DESIGN.md describes a system (colors, typography, spacing,
component recipes), not a screen, the importer does not emit a
ui.js. That's a deliberate split from the other import sources, which
all start from a screen export. Pair this importer with a separate
screen import (Figma, Stitch, Pencil, v0, Claude) when you want a full
UI; use it standalone when you only need to bring a token system into
Pulp.
Quickstart¶
Produces:
tokens.json— DTCG token tree with$typeand$valuefor every parsed key. Reference resolution is applied (see below). Composite typography references insidecomponents.*are preserved verbatim so downstream tooling can resolve them in context.
Does not produce:
ui.js— DESIGN.md has no screen. Phase 3 will scaffold widgets fromcomponents.*, but Phase 1 stops at tokens.classnames.json— that artifact is specific to theclaudesource.- Any bridge or React scaffold — there's no view to render.
Detect-only (no file writes):
Supported subset¶
Phase 1 parses the canonical frontmatter keys. Everything else passes through as opaque strings, mirroring the upstream spec's "ignore unknowns" policy.
| Key | Parsed | Notes |
|---|---|---|
version |
yes | Stored on the IR; not emitted into tokens.json. |
name |
yes | Required for detection. Stored on the IR. |
description |
yes | Block scalars (|, >) handled by yaml-cpp. |
colors.* |
yes | Each entry becomes a color token. |
typography.* |
yes | Composite typography tokens with fontFamily, fontSize, fontWeight, lineHeight, fontFeature, fontVariation. |
rounded.* |
yes | dimension tokens. |
spacing.* |
yes | dimension tokens. Non-dimensional values (e.g. "5") are preserved as strings. |
components.* |
yes | Each component is a flat map of token references and literal style values. References are not resolved at parse time (see below). |
| Unknown top-level keys | passthrough | Stored on the IR, not emitted into tokens.json. The parser warns once per unknown key. |
| Unknown component properties | passthrough | Per the spec, unknown component props are preserved as opaque strings. |
When frontmatter is present it is the sole token source; the Markdown body
after the closing --- fence is parsed for headings only (Phase 2's
pulp design lint will use the body for cross-references between sections
and prose).
When a file has no frontmatter, the parser falls back to scanning the
Markdown body so prose-authored files (common for Stitch / Brand-Kit
exports) don't import as an empty token set. It reads name: value list
items and | name | value | table rows under these sections:
| Body section | Tokens |
|---|---|
## Colors / ## Color Palette |
color tokens (header/separator rows skipped) |
## Spacing |
spacing-<name> dimensions |
## Border Radius / ## Rounded |
rounded-<name> dimensions |
## Shadows / ## Elevation |
shadow-<name> string tokens |
A ### Light Mode / ### Dark Mode subsection under ## Colors routes
values to the bare token name (light/default) or a <name>.dark suffix
(dark) — the same multi-mode convention the Figma plugin uses, so dark
themes land in the flat token maps.
Reference resolution¶
DESIGN.md uses {group.key} for references. Pulp's resolver runs at
parse time:
| Reference | Resolves to | Behavior |
|---|---|---|
{colors.primary} |
#1A1C1E (the literal value) |
Inlined in the emitted token's $value. |
{colors} |
(group reference) | Outside components.*: emits a designmd.broken-ref warning. DTCG has no concept of a group alias. |
{typography.label-md} |
(composite) | Inside components.*: preserved verbatim in the component's $value. Outside components.*: warns. |
Cycle detection is depth-limited at 10 hops; deeper chains warn and
stop expanding. Unresolved references ({colors.does-not-exist}) emit
a designmd.broken-ref diagnostic at the reference's source line and
leave the literal {…} string in the output.
Detection¶
The designmd fingerprint in compat.json is all-of with a 95%
minimum confidence floor. All four clauses must match:
filename— the input file's basename matches^DESIGN\.md$(case-insensitive).frontmatter-fence— the file starts with a---line followed by another---line later in the document.frontmatter-key(required) — the frontmatter contains aname:key.frontmatter-key(any-of) — the frontmatter contains at least one ofcolors,typography,rounded,spacing,components.
The combination is intentionally strict. A generic Jekyll or Hugo blog
post with name: in its frontmatter will not match because it has no
canonical DESIGN.md token group. Three decoys live under
test/fixtures/imports/designmd/alpha/decoys/ and are exercised by
pulp-test-cli-import-detect:
jekyll/DESIGN.md— Jekyll post withname:andlayout:but no token groups → does not match.missing-name/DESIGN.md— hascolors:but noname:→ does not match.missing-token-groups/DESIGN.md— hasname:anddescription:but no canonical token groups → does not match.
A --detect-only invocation on a real DESIGN.md prints:
detected source: designmd
format-version: alpha
parser-version: 0.1
fingerprint match: 4/4 (filename, frontmatter-fence, frontmatter-key[name], frontmatter-key[colors|typography|rounded|spacing|components])
confidence: 100%
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Success — tokens.json written (or detect-only match printed). |
1 |
Usage error or write failure (missing --file, unwritable --tokens path, permission denied). |
2 |
Detect-only run found no match. |
3 |
Parse error — malformed YAML frontmatter, duplicate top-level section, missing closing fence. |
4 |
Unsupported feature — encountered a construct the parser explicitly rejects rather than silently dropping (reserved; nothing currently triggers it in Phase 1). |
Diagnostics¶
The parser emits one diagnostic per line on stderr in this format:
Example:
[warning] designmd.broken-ref at colors.accent (14:12): reference {colors.does-not-exist} could not be resolved
[warning] designmd.unknown-section at extras (42:1): top-level key 'extras' is not part of the canonical schema; preserved as opaque string
[error] designmd.duplicate-section at colors (3:1): 'colors' appears more than once in frontmatter
severity is one of error (exit code 3 or 4), warning (does not
affect exit code), or info (suppressed unless --debug).
Phase 1 contract¶
Phase 1 ships exactly the surface above:
pulp import-design --from designmd→tokens.json.- Detection in
compat.jsonwith the strict fingerprint. - Test fixtures (paws-and-paths from upstream, plus a hand-authored edge-case fixture and three decoys).
- This documentation page and the cross-references listed below.
Phase 2 will add pulp design lint (token coverage, broken refs,
unused tokens, naming conventions, contrast ratios, body/frontmatter
drift, unknown sections), pulp design diff (semantic diff between
two DESIGN.md files), and Tailwind v3 + v4 exporters.
Phase 3 will treat DESIGN.md as a project source of truth: pulp
design hydrates the live theme from DESIGN.md; pulp design save
--update-design-md round-trips changes back. Component scaffolding
from components.* into Pulp widgets lands in the same phase.
Not yet supported¶
- Tailwind v3 / v4 export — Phase 2.
- Live runtime hydration of Pulp's theme from a DESIGN.md file — Phase 3.
- Widget scaffolding from
components.*— Phase 3. - An
npx @google/design.md specequivalent — out of scope. Pulp ships the format documentation as this page; the upstream spec at github.com/google-labs-code/design.md remains authoritative for the format itself.
Attribution¶
- yaml-cpp (MIT) is vendored to parse the frontmatter; see
DEPENDENCIES.mdfor the pin andNOTICE.mdfor the formal license text. - The
paws-and-pathstest fixture undertest/fixtures/imports/designmd/alpha/DESIGN.mdis copied verbatim from the upstream google/design.md repository (Apache-2.0).NOTICE.mdcarries the upstream attribution alongside the project's other third-party notices.