What is DSDS?
DSDS (Design System Documentation Standard) is a JSON-based format for documenting design systems. It gives every piece of documentation — components, tokens, themes, styles, patterns — a predictable, machine-readable structure.
Key idea: DSDS documents the how and why of your design system — not the token values themselves. It complements the W3C Design Tokens Format which handles the what.
What you get
- Structured — every section has a defined shape, no guessing
- Machine-readable — tools can parse, generate, validate, and transform it
- Portable — not locked to any docs tool or platform
- Extensible — add vendor metadata without breaking compatibility
- Validatable — JSON Schema catches errors before they reach consumers
Document structure
A DSDS file is a JSON document with a version and one or more documentation groups. Each group contains an array of typed entities.
{
"dsdsVersion": "0.1",
"documentation": [
{
"name": "My Design System",
"components": [
{ "kind": "component", "name": "button", "...": "" }
],
"tokenGroups": [
{ "kind": "token-group", "name": "color-palette", "...": "" }
],
"themes": [
{ "kind": "theme", "name": "dark", "...": "" }
]
}
]
}
That's the full top-level structure:
- dsdsVersion — always "0.1" for this version
- documentation — array of named groups, each with typed entity arrays
- components, tokenGroups, themes, styles, patterns — separate arrays for each entity type. All are optional — include only the ones you need.
Tip: You can split entities into groups — one for base styles, one for components, one for tokens. Or put them all in one group. The schema allows both.
Entity types
Every entity has a kind field that tells tools what type of thing it is. There are six kinds.
| Kind | Code | Description |
|---|
| component | "component" | A reusable UI element — buttons, inputs, modals. Supports anatomy, API, variants, states, and design specs. |
| token | "token" | A single design token — color, spacing, typography. Carries type, category, and usage rules. Link to W3C DTCG definitions via source. |
| token-group | "token-group" | A nested group of related tokens. Recursive — groups can contain groups. |
| theme | "theme" | A named set of token overrides — dark mode, high-contrast, compact density, brand variants. Lists which token names change; the DTCG file holds the actual values. |
| style | "style" | A design base — color, typography, spacing, elevation. Carries principles, scales, and motion definitions. |
| pattern | "pattern" | A broad action pattern — nav, error messaging, empty states. Describes how components compose to solve a user need. |
Common properties
Every entity shares these fields:
| Property | Required | Description |
|---|
| kind | Yes | Entity type |
| name | Yes* | Machine-readable ID (^[a-z][a-z0-9-]*$, except tokens) |
| displayName | Yes* | Human-readable label |
| description | Yes* | What this entity is and does (CommonMark supported) |
| status | No | "stable", "experimental", "draft", "deprecated" — or an object with per-platform status |
| since | No | Version when this entity first shipped |
| tags | No | Array of freeform category tags |
| documentBlocks | No | Array of typed document block objects |
| agents | No | Agent-optimized context for AI/LLM consumption |
* Required for component, style, and pattern. Token requires name + tokenType.
The optional agents object provides context written for AI/LLM consumers — intent for quick relevance checks, keywords for retrieval, constraints with enforcement levels, disambiguation against similar entities, and antiPatterns with corrective alternatives.
Status: string or object
For the simple case, status is a string:
{ "status": "stable" }
When you need per-platform tracking:
{
"status": {
"overall": "stable",
"platforms": {
"react": { "status": "stable", "since": "1.0.0" },
"ios": { "status": "experimental", "since": "3.0.0" }
}
}
}
The document block system
Structured docs live in the documentBlocks array on each entity. Each document block entry is typed by its kind field.
| Kind | Applies To | Description |
|---|
| anatomy | component, pattern | Named parts that make up the entity, with optional design-token mapping per part |
| api | component | Properties, events, slots, and CSS custom properties |
| events | component, pattern | Events emitted by the component — trigger conditions, payloads, DOM behavior |
| variants | component, pattern | Named variant axes (e.g. size, color) with discrete values |
| states | component, pattern | Interactive states (hover, disabled, …) with per-state token overrides |
| purpose | all | When to use / when not to use, with options for negative cases |
| guideline | all | Actionable guidance paired with rationale and enforcement level |
| accessibility | component, pattern | WCAG level, keyboard interactions, ARIA attributes, screen-reader behavior |
| content | component, pattern | Writing and labelling guidelines for UI text |
| interaction | component, pattern | Step-by-step action flows with optional wireframes |
| design-specifications | component, pattern | Concrete measurements, spacing, and sizing values for implementors |
| scale | style | Named stops along a design scale (e.g. spacing-100…spacing-900) |
| motion | style | Named animation/transition presets with duration, easing, and purpose |
| principle | style | Guiding design principles with rationale and examples |
Every document block type also accepts an optional agents property for AI/LLM-optimized context scoped to that section. See Schema Architecture for details.
Purpose: when to use it
The purpose guideline lists scenarios. Each use case is "positive" (do use) or "negative" (don't use, with an option):
{
"kind": "purpose",
"useCases": [
{
"description": "When the user needs to trigger an action such as submitting a form.",
"kind": "positive"
},
{
"description": "When the action navigates to a different page.",
"kind": "negative",
"alternative": {
"name": "link",
"rationale": "Links carry native navigation semantics."
}
}
]
}
Guidelines: how to use it
Each guideline pairs a guidance statement with a rationale and an enforcement level:
{
"kind": "guideline",
"items": [
{
"guidance": "Limit each surface to one primary button.",
"rationale": "Multiple primary buttons dilute visual hierarchy.",
"kind": "required",
"category": "visual-design"
}
]
}
Enforcement levels: required (MUST), encouraged (SHOULD), informational (MAY, default), discouraged (SHOULD NOT), prohibited (MUST NOT).
Minimal examples
These are the smallest valid entities — the bare minimum. Copy one, fill in your content, and add document block entries as you go.
Component
A component needs kind, name, displayName, and description. Everything else is optional.
{
"kind": "component",
"name": "button",
"displayName": "Button",
"metadata": [
{
"kind": "description",
"value": "A clickable element that triggers an action."
},
{
"kind": "status",
"status": "stable"
},
{
"kind": "category",
"value": "action"
}
],
"documentBlocks": [
{
"kind": "purpose",
"useCases": [
{
"description": "When the user needs to trigger an action such as submitting a form or confirming a dialog.",
"kind": "positive"
},
{
"description": "When the action is navigation to another page.",
"kind": "negative",
"alternative": {
"name": "link",
"rationale": "Links communicate navigation; buttons communicate actions."
}
}
],
"agents": {
"intent": "Clarify when to use this component.",
"keywords": [
"when to use",
"use case"
]
}
}
],
"agents": {
"intent": "Trigger a user-initiated action within the current view without causing page navigation.",
"constraints": [
{
"rule": "Do not use for navigating to a different page or URL.",
"level": "must-not"
},
{
"rule": "Limit each surface to one primary-emphasis button.",
"level": "must"
},
{
"rule": "Always provide an accessible label via visible text or aria-label.",
"level": "must"
}
],
"disambiguation": [
{
"entity": "link",
"distinction": "Use button for in-page actions; use link for navigation to a URL."
},
{
"entity": "icon-button",
"distinction": "Use button when a visible text label is present; use icon-button for icon-only affordances."
}
],
"antiPatterns": [
{
"description": "Using a button to navigate to another page.",
"instead": "Use a link element with href."
},
{
"description": "Placing multiple primary buttons on the same surface.",
"instead": "Use one primary and one or more secondary or tertiary buttons."
}
],
"keywords": [
"action",
"submit",
"click",
"CTA",
"trigger",
"call-to-action",
"interactive"
]
}
}
Token
A token needs kind, name, and tokenType. Use the optional source property to link back to the W3C DTCG file that holds the authoritative value.
{
"kind": "token",
"name": "color-text-primary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.primary"
}
}
Token group
Groups arrange tokens in a tree. The children array can contain tokens or nested groups.
{
"kind": "token-group",
"name": "color-text",
"metadata": [
{
"kind": "description",
"value": "Semantic text color tokens."
},
{
"kind": "status",
"status": "stable"
},
{
"kind": "category",
"value": "semantic"
}
],
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text"
},
"children": [
{
"kind": "token",
"name": "color-text-primary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.primary"
}
},
{
"kind": "token",
"name": "color-text-secondary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.secondary"
}
},
{
"kind": "token",
"name": "color-text-disabled",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.disabled"
}
}
],
"agents": {
"intent": "Define and organize a set of related design tokens, providing shared defaults for type and category.",
"constraints": [
{
"rule": "Do not reference base palette tokens directly in component code.",
"level": "must-not",
"context": "Always reference semantic tokens that point to palette values."
}
],
"keywords": [
"token",
"group",
"palette",
"scale",
"family",
"collection"
]
}
}
Theme
A theme provides overrides — an array of token names that differ from the default. The DTCG file holds the actual override values.
{
"kind": "theme",
"name": "dark",
"displayName": "Dark Mode",
"metadata": [
{
"kind": "description",
"value": "Dark color mode for reduced-light environments."
},
{
"kind": "status",
"status": "stable"
},
{
"kind": "category",
"value": "color-mode"
}
],
"overrides": [
{
"token": "color-background-default",
"description": "Inverted default surface for dark mode."
},
{
"token": "color-text-primary",
"description": "High-contrast text on dark surfaces."
},
{
"token": "color-border-default",
"description": "Subtle border visible on dark backgrounds."
}
],
"agents": {
"intent": "Apply a dark color palette for low-light environments and user preference, maintaining WCAG AA contrast throughout.",
"constraints": [
{
"rule": "Always apply at the application root, not on individual components.",
"level": "must"
},
{
"rule": "Do not mix dark-mode and light-mode semantic tokens on the same surface.",
"level": "must-not"
}
],
"disambiguation": [
{
"entity": "high-contrast",
"distinction": "Use dark for low-light comfort; use high-contrast for users with low vision requiring maximum contrast."
}
],
"antiPatterns": [
{
"description": "Applying dark theme only to part of a page while the rest remains light.",
"instead": "Use inline theme switching for isolated components; apply the theme at the root for global coverage."
}
],
"keywords": [
"dark-mode",
"color-mode",
"night",
"low-light",
"theme",
"override"
]
}
}
Style
A style documents a design base. Guidelines like principles, scale, and motion are specific to styles.
{
"kind": "style",
"name": "spacing",
"displayName": "Spacing",
"metadata": [
{
"kind": "description",
"value": "The spatial system governing layout rhythm and component density."
},
{
"kind": "status",
"status": "stable"
}
],
"documentBlocks": [
{
"kind": "principles",
"items": [
{
"title": "Use the scale",
"description": "Always pick a value from the spacing scale. Avoid arbitrary pixel values."
}
],
"agents": {
"intent": "State the foundational beliefs governing this style.",
"keywords": [
"principles",
"guidelines"
]
}
}
],
"agents": {
"intent": "Document spacing scale tokens and enforce their consistent application across layout, components, and typography.",
"constraints": [
{
"rule": "Do not substitute spacing tokens with typography or icon-size tokens.",
"level": "must-not"
},
{
"rule": "Always use the next scale step up or down rather than custom values.",
"level": "should"
}
],
"disambiguation": [
{
"entity": "typography style",
"distinction": "Spacing governs whitespace and layout gaps; typography governs type size, weight, and line height."
}
],
"keywords": [
"spacing",
"scale",
"gap",
"padding",
"margin",
"whitespace",
"layout",
"density"
]
}
}
Pattern
A pattern describes how components compose to solve a user need. It supports interactions for flow steps.
{
"kind": "pattern",
"name": "form-validation",
"displayName": "Form Validation",
"metadata": [
{
"kind": "description",
"value": "Validates user input on form submission and communicates errors inline."
},
{
"kind": "status",
"status": "stable"
},
{
"kind": "links",
"items": [
{
"kind": "component",
"name": "form-field",
"role": "Displays inline error messages",
"required": true
},
{
"kind": "component",
"name": "button",
"role": "Triggers form submission",
"required": true
},
{
"kind": "component",
"name": "toast",
"role": "Confirms successful submission"
}
]
}
],
"agents": {
"intent": "Guide multi-component composition for surfacing, communicating, and resolving form validation errors.",
"constraints": [
{
"rule": "Always include both an inline field error and a summary when multiple fields fail.",
"level": "must"
},
{
"rule": "Do not use toast notifications as the sole error communication for form validation.",
"level": "must-not"
}
],
"disambiguation": [
{
"entity": "empty-state",
"distinction": "Use error-messaging for validation and system errors; use empty-state for the absence of content."
},
{
"entity": "alert",
"distinction": "Use error-messaging for form validation flows; use alert for non-form system or status messages."
}
],
"antiPatterns": [
{
"description": "Showing errors only on submit without inline field feedback.",
"instead": "Show inline errors on field blur and in a summary on submit."
}
],
"keywords": [
"error",
"validation",
"form",
"feedback",
"inline-error",
"error-summary",
"alert"
]
}
}
Full document {#minimal}
Here's a complete, minimal DSDS file with one of each entity type:
{
"$schema": "../schema/dsds.bundled.schema.json",
"dsdsVersion": "0.1",
"metadata": {
"systemName": "Minimal Example"
},
"documentation": [
{
"name": "Minimal Design System",
"components": [
{
"kind": "component",
"name": "button",
"displayName": "Button",
"metadata": [
{
"kind": "description",
"value": "A clickable button for triggering actions."
},
{
"kind": "status",
"status": "stable"
}
],
"agents": {
"intent": "Trigger a user-initiated action within the current view without causing page navigation.",
"constraints": [
{
"rule": "Do not use for navigating to a different page or URL.",
"level": "must-not"
},
{
"rule": "Limit each surface to one primary-emphasis button.",
"level": "must"
},
{
"rule": "Always provide an accessible label via visible text or aria-label.",
"level": "must"
}
],
"disambiguation": [
{
"entity": "link",
"distinction": "Use button for in-page actions; use link for navigation to a URL."
},
{
"entity": "icon-button",
"distinction": "Use button when a visible text label is present; use icon-button for icon-only affordances."
}
],
"antiPatterns": [
{
"description": "Using a button to navigate to another page.",
"instead": "Use a link element with href."
},
{
"description": "Placing multiple primary buttons on the same surface.",
"instead": "Use one primary and one or more secondary or tertiary buttons."
}
],
"keywords": [
"action",
"submit",
"click",
"CTA",
"trigger",
"call-to-action",
"interactive"
]
}
}
],
"tokenGroups": [
{
"kind": "token-group",
"name": "tokens",
"children": [
{
"kind": "token",
"name": "color-text-primary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.primary"
}
},
{
"kind": "token",
"name": "color-text-secondary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.secondary"
}
}
],
"agents": {
"intent": "Define and organize a set of related design tokens, providing shared defaults for type and category.",
"constraints": [
{
"rule": "Do not reference base palette tokens directly in component code.",
"level": "must-not",
"context": "Always reference semantic tokens that point to palette values."
}
],
"keywords": [
"token",
"group",
"palette",
"scale",
"family",
"collection"
]
}
},
{
"kind": "token-group",
"name": "color-text",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text"
},
"children": [
{
"kind": "token",
"name": "color-text-primary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.primary"
}
},
{
"kind": "token",
"name": "color-text-secondary",
"tokenType": "color",
"source": {
"file": "tokens/color.tokens.json",
"path": "color.text.secondary"
}
}
],
"agents": {
"intent": "Define and organize a set of related design tokens, providing shared defaults for type and category.",
"constraints": [
{
"rule": "Do not reference base palette tokens directly in component code.",
"level": "must-not",
"context": "Always reference semantic tokens that point to palette values."
}
],
"keywords": [
"token",
"group",
"palette",
"scale",
"family",
"collection"
]
}
}
],
"themes": [
{
"kind": "theme",
"name": "dark",
"displayName": "Dark Mode",
"metadata": [
{
"kind": "description",
"value": "Dark color mode for low-light environments."
},
{
"kind": "status",
"status": "stable"
}
],
"overrides": [
{
"token": "color-text-primary",
"description": "High-contrast text on dark surfaces."
},
{
"token": "color-text-secondary",
"description": "Muted text for secondary content in dark mode."
}
],
"agents": {
"intent": "Apply a dark color palette for low-light environments and user preference, maintaining WCAG AA contrast throughout.",
"constraints": [
{
"rule": "Always apply at the application root, not on individual components.",
"level": "must"
},
{
"rule": "Do not mix dark-mode and light-mode semantic tokens on the same surface.",
"level": "must-not"
}
],
"disambiguation": [
{
"entity": "high-contrast",
"distinction": "Use dark for low-light comfort; use high-contrast for users with low vision requiring maximum contrast."
}
],
"antiPatterns": [
{
"description": "Applying dark theme only to part of a page while the rest remains light.",
"instead": "Use inline theme switching for isolated components; apply the theme at the root for global coverage."
}
],
"keywords": [
"dark-mode",
"color-mode",
"night",
"low-light",
"theme",
"override"
]
}
}
],
"styles": [
{
"kind": "style",
"name": "color",
"displayName": "Color",
"metadata": [
{
"kind": "description",
"value": "The color system governing palette usage, semantic mapping, and accessibility."
},
{
"kind": "status",
"status": "stable"
}
],
"agents": {
"intent": "Document spacing scale tokens and enforce their consistent application across layout, components, and typography.",
"constraints": [
{
"rule": "Do not substitute spacing tokens with typography or icon-size tokens.",
"level": "must-not"
},
{
"rule": "Always use the next scale step up or down rather than custom values.",
"level": "should"
}
],
"disambiguation": [
{
"entity": "typography style",
"distinction": "Spacing governs whitespace and layout gaps; typography governs type size, weight, and line height."
}
],
"keywords": [
"spacing",
"scale",
"gap",
"padding",
"margin",
"whitespace",
"layout",
"density"
]
}
}
],
"patterns": [
{
"kind": "pattern",
"name": "form-validation",
"displayName": "Form Validation",
"metadata": [
{
"kind": "description",
"value": "Validates user input and communicates errors on form submission."
},
{
"kind": "status",
"status": "stable"
}
],
"agents": {
"intent": "Guide multi-component composition for surfacing, communicating, and resolving form validation errors.",
"constraints": [
{
"rule": "Always include both an inline field error and a summary when multiple fields fail.",
"level": "must"
},
{
"rule": "Do not use toast notifications as the sole error communication for form validation.",
"level": "must-not"
}
],
"disambiguation": [
{
"entity": "empty-state",
"distinction": "Use error-messaging for validation and system errors; use empty-state for the absence of content."
},
{
"entity": "alert",
"distinction": "Use error-messaging for form validation flows; use alert for non-form system or status messages."
}
],
"antiPatterns": [
{
"description": "Showing errors only on submit without inline field feedback.",
"instead": "Show inline errors on field blur and in a summary on submit."
}
],
"keywords": [
"error",
"validation",
"form",
"feedback",
"inline-error",
"error-summary",
"alert"
]
}
}
]
}
]
}
Validate your document
DSDS ships with a JSON Schema for validating your documents.
Using the bundled schema
Add $schema to get editor autocompletion and inline validation:
{
"$schema": "https://designsystemdocspec.org/v0.1/dsds.bundled.schema.json",
"dsdsVersion": "0.1",
"documentation": []
}
Using the CLI
# Clone the repo
git clone https://github.com/somerandomdude/design-system-documentation-schema.git
cd design-system-documentation-schema
npm install
# Validate the built-in examples
npm run validate
# Validate your own file
npx ajv validate -s spec/schema/dsds.bundled.schema.json -d my-system.dsds.json
Next steps
You've seen the basics. Here's where to go deeper.
| Resource | Description |
|---|
| Full Spec | Complete schema reference for every field and constraint |
| Interactive Samples | Side-by-side JSON ↔ rendered documentation for real-world entities |
| JSON Schema | The raw .schema.json files — use for editor autocompletion |
| Example Files | Complete, valid example documents for every entity and guideline type |
| GitHub Discussions | Ask questions, share ideas, propose changes |
Getting started recipe:
- Copy the minimal document above
- Replace the example entities with your own design system's components and tokens
- Add documentBlocks entries to each entity as your docs grow
- Validate with npm run validate to catch schema errors early
Design System Documentation Standard (DSDS) 0.1 — Draft Specification
GitHub