How the schema is organizedThis spec is built from a small, fixed set of shapes, reused rather than reinvented per file — each definition below documents its own fields directly. See Conformance in the README for how it's all enforced.
Every entry has a kind field. There are 5 well-known values, plus an open option for anything else.
| Kind | Description |
|---|
| system | The design system as a whole — version, organization, url, license, platforms, plus system-wide documentation. |
| component | A reusable UI element — buttons, inputs, modals. Carries its own sourceFiles, imports, traits (variants and states), and combos, on top of the fields every entry shares. |
| token | A single design token. Carries tokenType and a source pointer to the real DTCG value — never the value itself. |
| theme | A named set of token overrides — dark mode, high-contrast, a brand variant. Points at its own DTCG source file. |
| entry | The generic, open kind for anything else — a foundation, a pattern, a guide. Has no fields beyond what every entry shares. |
| (custom) | A custom kind like acme.icon-library, for a document that wants its own recognizable name instead of the generic entry. |
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ @@
@@ @@
@@ @@@@@@@@@@@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@ @@
@@ @@ @@ @@ @@
@@ @@ @@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@
@@ @@ @@ @@ @@ @@
@@ @@@@@@@@@@@ @@@@@@@@@@ @@
@@ @@
@@ @@@@@@@@@@@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@ @@
@@ @@ @@ @@ @@
@@ @@ @@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@
@@ @@ @@ @@ @@ @@
@@ @@@@@@@@@@@ @@@@@@@@@@ @@
@@ @@
@@ @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The version of this spec the document follows.
The name of the design system this document describes.
Every entry this document owns, listed directly.
Min items: 1
An optional hint for editor tools, like autocomplete or validate-on-save.
Reusable content that is not itself a design system artifact, for example an accessibility rule or a guideline that applies broadly.
Min items: 1
The same pointer type entries use.
Escape hatch for tool-specific document-level data, keyed by namespace.
References: dispatch, Shared, list, Extensions
schemaVersion: "0.20.0"
name: Acme Design System
$schema: https://designsystemdocspec.org/v0.20.0/dsds.bundled.yaml
entries:
- id: acme-design-system
kind: system
...
shared:
- id: shared-a11y
...
refs:
- href: ./starter-kit-fragments/button.dsds.yaml
rel: file
$extensions:
com.acme: {...}
This entry's unique id.
The human-readable display name.
A one-line statement of what this shared entry is for.
Pointers from this entry to other things.
The reusable content itself, in the same section structure an entry uses.
Min items: 1
Escape hatch for tool data or an outside id, the same structure as an entry's own $extensions.
References: Id, Metadata, list, dispatch, Extensions
- id: shared-a11y
name: Shared Accessibility Rules
description: Cross-cutting accessibility rules, stated once and referenced from every entry they apply to.
metadata:
status: {status: stable}
refs:
- href: https://www.w3.org/WAI/WCAG21/quickref/
rel: external-link
sections:
- kind: guidelines
for: all
items:
- id: touch-target
statement: Minimum touch target 44x44px.
level: must
$extensions:
com.acme: {...}
The subject of what elements can or cannot be paired with. Can be a trait, token, or entry id.
The elements paired with the subject.
Min items: 1
Whether the elements in items can or cannot be paired with the subject—and how strict the rule is.
Why this rule holds.
References: #/$defs/target, RequirementLevel, Id
combos:
- subject: "{color.action.primary}"
level: must
items: ["{color.surface.default}", "{color.surface.raised}"]
note: Contrast is verified only against these surfaces; on any other background the label ratio is unproven.
Constraints: at least one of:
References: Id
size.large # a bare id
"{color.action.primary}" # or a token reference
A short heading for the example.
Describes the example in detail.
A visual sample of this example.
Where this example lives in code.
At least one of title, description, showcase, ref must be present.
References: Showcase, Ref, Example
example:
title: One primary action per surface
description: A toolbar with one filled primary button and two lower-emphasis secondary buttons.
showcase:
kind: image
url: https://cdn.acme.example/ds/showcase/button-primary-surface.png
alt: A toolbar with one filled primary button and two lower-emphasis secondary buttons.
ref:
href: https://storybook.acme.example/?path=/story/button--primary
rel: storybook
References: Example
- title: One primary action per surface
showcase: {kind: image, url: https://cdn.acme.example/ds/showcase/button-primary-surface.png}
- title: Loading state
ref: {href: ./stories/button.stories.tsx, rel: storybook}
Open map: keys are strings, values are object
References: namespaced
$extensions:
com.acme:
rationale: Multiple primary buttons compete for attention and force the user to guess which action is actually the recommended one.
failureMode: A dialog ships with two primary-styled buttons (e.g. "Save" and "Save as draft"), and usability testing shows users default to the wrong one.
Values must match ^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)*$.
id: color.action.primary
Values must match ^[a-z0-9]+(-[a-z0-9]+)*([./][a-z0-9]+(-[a-z0-9]+)*)*$.
color/action/primary
Values must match ^[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)+$.
acme.icon-library
statement: Do not use button when the action navigates to a new URL; use the link entry instead.
Accepts one of:
- string — Shorthand for an external link that doesn't need added definition. Equivalent to `{href: <string>}`.
- object
What kind of pointer this is, or a namespaced custom value.
What this points at, inside this document's own graph.
Pattern: ^[a-z0-9]+(-[a-z0-9]+)*([./][a-z0-9]+(-[a-z0-9]+)*)*(#[a-z0-9]+(-[a-z0-9]+)*(\.[a-z0-9]+(-[a-z0-9]+)*)*)?$
What this points at, outside this document. Such as a file, URL, or package.
What the thing being pointed at does in this context.
Additional info related to the connection of the two items.
References: namespaced, Ref
- href: https://example.atlassian.net/browse/DS-482
rel: external-link
role: Tracks the two-primary-buttons issue
note: Filed after a usability test surfaced the ambiguity.
# or, pointing inside this document instead of outside it:
- to: shared-a11y#touch-target
rel: same-as
References: Ref
- to: button
rel: depends-on
- href: https://storybook.acme.example
rel: storybook
Allowed values:
- must
- should
- should-not
- must-not
- may
- statement: Limit each surface to one primary button.
level: should
- statement: Use buttons only for in-page actions, never navigation.
level: must
What kind of media this showcase is.
Where the showcase lives.
Alt text describing the image or video, for accessibility
Provides additional detail about the showcase if needed.
showcase:
kind: image
url: https://cdn.acme.example/ds/showcase/button-primary-surface.png
alt: A toolbar with one filled primary button and two lower-emphasis secondary buttons.
note: Captured from the Storybook build, light theme.
since: 1.4.0
Keywords for grouping, search, and filtering. By convention, the first tag, if any, is the main category.
Min items: 1
The owning team, role, or group.
Independent reviews confirming this item's documentation, each recording who confirmed it and when.
Min items: 1
Why this entry was created, and how and why to use it.
When this item's documentation last changed.
How this entry's documentation came to exist, and who or what wrote it.
Escape hatch for tool data scoped to just this entry's metadata, keyed by namespace.
References: #/$defs/isoDate, Extensions
metadata:
tags: [actions, button, cta]
owner: ds@acme.example
reviewed:
- date: 2026-05-01
by: human:ahormati
note: Copy and contrast ratios re-checked; no changes needed.
context: Introduced to give agents extra information for how to use this entry.
updated:
date: 2026-06-02
note: Added the loading trait and its guideline.
origin:
method: generated
author: machine-generated
note: Generated from custom-elements.json (CEM schemaVersion 2.1.0) by cem-to-dsds.
$extensions:
com.acme: {...}
Reviewed against the latest Figma file; no changes needed.
Values must match ^\d{4}-\d{2}-\d{2}$.
2026-06-02
Keywords for grouping, search, and filtering. By convention, the first tag, if any, is the main category.
Min items: 1
The owning team, role, or group.
Independent reviews confirming this item's documentation, each recording who confirmed it and when.
Min items: 1
Why this entry was created, and how and why to use it.
When this item's documentation last changed.
How this entry's documentation came to exist, and who or what wrote it.
Escape hatch for tool data scoped to just this entry's metadata, keyed by namespace.
A lifecycle status, optionally scoped to one platform.
The version this entry was first introduced.
A group name this entry belongs to, for example "color.action" on a set of related tokens, or "action" on a family of related components.
Other names this entry is also known or searched by, like a past name or a common misspelling.
A visual sample of this entry, either a media file or a link.
References: Metadata, Id, #/$defs/statusValue, Since, Showcase, #/$defs/isoDate, Extensions
metadata:
status: {status: stable}
since: 1.4.0
group: color.action
aliases: [btn]
tags: [actions, button, cta, form-control]
owner: ds@acme.example
reviewed:
- date: 2026-05-01
by: human:ahormati
context: Introduced to give agents extra information for how to use this entry.
updated: {date: 2026-06-02, note: Added the loading trait and its guideline.}
origin: {method: authored, author: human}
preview: {kind: image, url: https://cdn.acme.example/ds/showcase/button.png}
$extensions:
com.acme: {...}
Values must match ^[a-z0-9]+(-[a-z0-9]+)*$.
stable
Keywords for grouping, search, and filtering. By convention, the first tag, if any, is the main category.
Min items: 1
The owning team, role, or group.
Independent reviews confirming this item's documentation, each recording who confirmed it and when.
Min items: 1
Why this entry was created, and how and why to use it.
When this item's documentation last changed.
How this entry's documentation came to exist, and who or what wrote it.
Escape hatch for tool data scoped to just this entry's metadata, keyed by namespace.
The current version of the design system.
The team or company that owns the design system.
The main home page or repository for the design system.
The license this design system is published under.
The platforms this system ships on, for example "react" or "web-component".
Min items: 1
References: Metadata, Since, Id, #/$defs/isoDate, Extensions
metadata:
version: 1.4.0
organization: Acme Corp
url: https://design.acme.example
license: MIT
platforms: [react, web-component]
tags: [design-system]
owner: ds@acme.example
reviewed:
- date: 2026-05-01
by: human:ahormati
context: Why this system exists, for an agent reading it.
updated: {date: 2026-06-02}
origin: {method: authored, author: human}
$extensions:
com.acme: {...}
This entry's unique id in the design system graph.
What kind of thing this entry is, as a real design-system artifact: one of the 5 well-known kinds, or a namespaced custom kind.
The human-readable display name.
A one-line statement of what this entry is or is for.
Explains the entry's reason for existing.
Information about a single entry, on top of the fields every metadata object shares.
Pointers to another entry this one is similar to in usage or purpose.
Pointers to another entry this one inherits from (rel: extends).
This entry's other pointers to entries and outside resources, not covered by related or extends.
Every documentation section for this entry.
Min items: 1
Escape hatch for tool data, or for an outside id that doesn't fit this schema's own id pattern.
References: namespaced, EntryMetadata, list, dispatch, Extensions, ComponentEntry, TokenEntry, ThemeEntry, SystemEntry, Entry
id: empty-state
kind: entry
name: Empty State
description: Composition of components shown when a view has no content to display yet.
purpose: Tells the user why an area is empty and what to do next.
metadata:
status: {status: stable}
related:
- to: error-state
rel: alternative-to
extends:
- to: base-dialog
rel: extends
refs:
- href: https://github.com/acme/ds/tree/main/patterns/empty-state
rel: source
sections:
- kind: guidelines
for: all
items:
- statement: Use an empty state the first time a list or grid has no content.
level: should
$extensions:
com.acme: {...}
References: ComponentEntry, TokenEntry, ThemeEntry, SystemEntry, Entry
- id: empty-state
kind: entry
name: Empty State
description: Composition of components shown when a view has no content yet.
- id: button
kind: component
...
This entry's unique id in the design system graph.
Marks this entry as a component.
The human-readable display name.
A one-line statement of what this entry is or is for.
Explains the entry's reason for existing.
Pointers to another entry this one is similar to in usage or purpose.
Pointers to another entry this one inherits from (rel: extends).
This entry's other pointers to entries and outside resources, not covered by related or extends.
Every documentation section for this entry.
Min items: 1
Escape hatch for tool data, or for an outside id that doesn't fit this schema's own id pattern.
One entry per platform's source file.
Min items: 1
Machine-readable API contract(s) for this component - props, slots, events, etc. in a standard, tool-readable shape.
One entry per platform.
Min items: 1
The component's variants and states. Each item is tagged kind: boolean or kind: enum, since the two carry genuinely different fields - an enum's own values list vs. a boolean's plain toggle.
Min items: 1
Define which of this component's own boolean traits or enum values can or cannot be paired with each other.
Min items: 1
References: Entry, EntryMetadata, Id, Ref, list, traitValue, traitSetBy, Combo, Markdown, list, Since, dispatch, Extensions
id: button
kind: component
name: Button
description: Triggers an action.
purpose: Gives users a single, consistent way to trigger an action.
metadata: {status: {status: stable}}
related: [{to: link, rel: alternative-to}]
extends: [{to: base-dialog, rel: extends}]
refs: [{href: https://github.com/acme/ds/react/button, rel: source}]
sections:
- kind: guidelines
for: all
items: [{statement: Limit each surface to one primary button., level: should}]
$extensions:
com.acme: {...}
sourceFiles:
- platform: react
file: ./src/Button.tsx
imports:
- platform: react
package: "@acme/ui"
traits:
- kind: boolean
id: loading
description: Shows a spinner in place of the label and blocks interaction while active.
setBy: consumer
combos:
- subject: loading
level: must-not
items: [disabled]
note: A control can't be simultaneously loading and disabled...
specs:
- rel: contract
href: ./contracts/button.contract.json
role: DS Contracts
Allowed values:
consumer # the caller passes this in, like size or variant
component # the component sets this on its own, like hover or loading
The machine-readable id.
What this is, how it looks or behaves, and any constraints.
The human-readable name. Uses id when left out.
Why this exists.
Examples showing this in context.
The version this was introduced.
References: Id, Markdown, list, Since
id: loading
name: Loading
description: Shows a spinner in place of the label and blocks interaction while active.
purpose: Prevents duplicate submissions while an action is in flight.
examples:
- title: Default loading state
showcase: {kind: image, url: https://cdn.acme.example/ds/showcase/button-loading.png}
since: 1.4.0
This entry's unique id in the design system graph.
Marks this entry as a design system.
The human-readable display name.
A one-line statement of what this entry is or is for.
Explains the entry's reason for existing.
Facts about the design system as a whole.
Pointers to another entry this one is similar to in usage or purpose.
Pointers to another entry this one inherits from (rel: extends).
This entry's other pointers to entries and outside resources, not covered by related or extends.
Every documentation section for this entry.
Min items: 1
Escape hatch for tool data, or for an outside id that doesn't fit this schema's own id pattern.
References: Entry, EntryMetadata, SystemMetadata, list, dispatch, Extensions
id: acme-design-system
kind: system
name: Acme Design System
description: Acme's cross-platform design system.
purpose: One source of truth for how Acme builds and documents interfaces.
metadata:
version: 1.4.0
organization: Acme Corp
url: https://design.acme.example
license: MIT
platforms: [react, web-component]
status: {status: stable}
related: [{to: acme-brand-system, rel: pairs-with}]
extends: [{to: base-design-system, rel: extends}]
refs: [{to: button, rel: composes}]
sections:
- kind: section
for: all
title: Getting started
freeform: [{title: Install, body: Add the package and its peer dependencies.}]
$extensions:
com.acme: {...}
This entry's unique id in the design system graph.
Marks this entry as a theme.
The human-readable display name.
A one-line statement of what this entry is or is for.
Explains the entry's reason for existing.
Pointers to another entry this one is similar to in usage or purpose.
Pointers to another entry this one inherits from (rel: extends).
This entry's other pointers to entries and outside resources, not covered by related or extends.
Every documentation section for this entry.
Min items: 1
Escape hatch for tool data, or for an outside id that doesn't fit this schema's own id pattern.
Path to the theme's DTCG source file.
Which native color-scheme setting this theme matches.
Default: "light"
References: Entry, EntryMetadata, Ref, list, dispatch, Extensions
id: dark
kind: theme
name: Dark
description: Inverted-luminance theme for low-light surfaces and user preference.
purpose: Lets a product opt into a dark color scheme without redefining every token.
metadata: {status: {status: stable}}
related: [{to: light, rel: pairs-with}]
extends:
- to: light
rel: extends
refs:
- href: https://www.figma.com/file/acme-dark-theme
rel: design
sections:
- kind: guidelines
for: all
items: [{statement: Test contrast against both themes before shipping., level: should}]
$extensions:
com.acme: {...}
source: tokens/dark.tokens.json
colorScheme: dark
This token's unique id.
Marks this entry as a token.
The human-readable display name.
A one-line statement of what this entry is or is for.
Explains the entry's reason for existing.
Pointers to another entry this one is similar to in usage or purpose.
Pointers to another entry this one inherits from (rel: extends).
This entry's other pointers to entries and outside resources, not covered by related or extends.
Every documentation section for this entry.
Min items: 1
Escape hatch for tool data, or for an outside id that doesn't fit this schema's own id pattern.
Path to the token's DTCG source file's token reference.
The token's type, from DTCG.
Pattern: ^[a-z][a-zA-Z0-9]*$
Rules about which other tokens this one must or must never be paired with.
Min items: 1
References: Entry, EntryMetadata, tokenId, Ref, Combo, list, dispatch, Extensions
id: space-4
kind: token
name: Space 4
description: A single step on the base spacing scale - 4 times the 4px base unit.
purpose: Keeps spacing consistent across components without hand-picked pixel values.
metadata: {status: {status: stable}, group: space}
related: [{to: space-8, rel: pairs-with}]
extends: [{to: space-base, rel: extends}]
refs: [{href: https://www.figma.com/file/acme-spacing-scale, rel: design}]
sections:
- kind: guidelines
for: all
items: [{statement: Use for default padding/gap; use space-8 for section spacing., level: should}]
$extensions:
com.acme: {...}
tokenType: spacing
source: ./tokens.dtcg.json
combos:
- subject: "{color.action.primary}"
level: must
items: ["{color.surface.default}", "{color.surface.raised}"]
What kind of content section this is.
Who or what this section is written for.
Default: "all"
The one universal list for this section kind's own structured content.
Nestable written content that can include headings. Available on every section kind regardless of items' own structure.
Min items: 1
An optional heading for the section.
An optional one-line intro for the section.
What job this section is doing.
Optional information about an element.
Escape hatch for tool data scoped to just this one section, keyed by namespace.
At least one of items, freeform must be present.
References: namespaced, Metadata, #/$defs/freeformEntry, Extensions, DefinitionsSection, GuidelinesSection, StepsSection, Section, Id, Markdown, list, list
- kind: section
for: all
title: Troubleshooting
description: Common problems and how to fix them.
context: acme.troubleshooting
metadata: {status: {status: stable}}
items:
- title: Note
body: Generic items have no fixed shape - use freeform for prose instead.
freeform:
- title: Styles don't apply
body: Confirm the base theme is imported before any component renders - a component's own CSS assumes the theme's custom properties already exist.
$extensions:
com.acme: {...}
References: DefinitionsSection, GuidelinesSection, StepsSection, Section
- kind: guidelines
for: all
items:
- statement: Limit each surface to one primary button.
level: should
- kind: steps
...
The entry's heading, for example 'Installation'.
A stable id for linking to this entry directly, unique within the section.
The entry's content.
One or more examples, in order.
"See also" pointers for this entry. To point at another entry, use the entry's own top-level refs instead.
Sub-entries nested beneath this one, to any depth.
Min items: 1
Escape hatch for tool data scoped to just this one freeform entry, keyed by namespace.
References: Id, Markdown, list, list, #/$defs/freeformEntry, Extensions
title: Install
id: install
body: Add the package and its peer dependencies.
examples:
- title: Install with the CLI
ref: {href: ./install.sh, rel: file}
refs:
- to: getting-started
rel: see-also
items:
- title: Peer dependencies
body: React 18+ and a theme provider higher in the tree.
$extensions:
com.acme: {...}
Marks this section as term-definition documentation.
Who or what this section is written for.
Default: "all"
An optional heading for the section.
An optional one-line intro for the section.
What job this section is doing.
Optional information about an element.
One entry per term.
Min items: 1
Nestable written content that can include headings. Available on every section kind regardless of items' own structure.
Min items: 1
Escape hatch for tool data scoped to just this one section, keyed by namespace.
References: Section, Id, Markdown, Extensions, namespaced, Metadata, #/$defs/freeformEntry
- kind: definitions
for: all
title: Terms
description: Words used in this component's copy.
context: terms
metadata: {status: {status: stable}}
items:
- term: OK
definition: To confirm an action.
- term: Cancel
definition: To cancel an action.
freeform:
- title: About
body: These terms match the ones used in product copy guidelines.
$extensions:
com.acme: {...}
Marks this section as guidelines.
Who or what this section is written for.
Default: "all"
An optional heading for the section.
An optional one-line intro for the section.
What job this section is doing.
Optional information about an element.
The rules, in order.
Min items: 1
Nestable written content that can include headings. Available on every section kind regardless of items' own structure.
Min items: 1
Escape hatch for tool data scoped to just this one section, keyed by namespace.
Which kind of guidance this section holds.
Default: "how-to-use"
References: Section, Id, Markdown, RequirementLevel, Example, list, Extensions, namespaced, Metadata, #/$defs/freeformEntry
- kind: guidelines
for: agent
framing: when-to-use
title: When to use
description: Whether button is the right choice for this action.
context: acme.fit-check
metadata: {status: {status: stable}}
items:
- statement: Do not use button when the action navigates to a new URL; use the link entry instead.
level: must-not
alternatives:
- to: link
rel: alternative-to
freeform:
- title: Why this matters
body: A button that navigates breaks browser back/forward and "open in new tab."
$extensions:
com.acme: {...}
Marks this section as a stepped process or checklist.
Who or what this section is written for.
Default: "all"
An optional heading for the section.
An optional one-line intro for the section.
What job this section is doing.
Optional information about an element.
The steps or checklist entries, in order.
Min items: 1
Nestable written content that can include headings. Available on every section kind regardless of items' own structure.
Min items: 1
Escape hatch for tool data scoped to just this one section, keyed by namespace.
Whether entries must be done in order. Set to false for an unordered checklist.
Default: true
References: Section, Id, Markdown, list, list, Extensions, namespaced, Metadata, #/$defs/freeformEntry
- kind: steps
for: agent
ordered: false
title: Pre-release checklist
description: Run through before shipping a change to this component.
context: acme.checklist
metadata: {status: {status: stable}}
items:
- title: Focus ring is visible in both light and dark themes.
- title: Loading state announces to screen readers.
- title: Works with a custom icon in the leading-icon slot.
optional: true
freeform:
- title: Why this matters
body: Skipping this checklist is how contrast regressions ship.
$extensions:
com.acme: {...}