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.

KindCodeDescription
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:

PropertyRequiredDescription
kindYesEntity type
nameYes*Machine-readable ID (^[a-z][a-z0-9-]*$, except tokens)
displayNameYes*Human-readable label
descriptionYes*What this entity is and does (CommonMark supported)
statusNo"stable", "experimental", "draft", "deprecated" — or an object with per-platform status
sinceNoVersion when this entity first shipped
tagsNoArray of freeform category tags
documentBlocksNoArray of typed document block objects
agentsNoAgent-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.

KindApplies ToDescription
anatomycomponent, patternNamed parts that make up the entity, with optional design-token mapping per part
apicomponentProperties, events, slots, and CSS custom properties
eventscomponent, patternEvents emitted by the component — trigger conditions, payloads, DOM behavior
variantscomponent, patternNamed variant axes (e.g. size, color) with discrete values
statescomponent, patternInteractive states (hover, disabled, …) with per-state token overrides
purposeallWhen to use / when not to use, with options for negative cases
guidelineallActionable guidance paired with rationale and enforcement level
accessibilitycomponent, patternWCAG level, keyboard interactions, ARIA attributes, screen-reader behavior
contentcomponent, patternWriting and labelling guidelines for UI text
interactioncomponent, patternStep-by-step action flows with optional wireframes
design-specificationscomponent, patternConcrete measurements, spacing, and sizing values for implementors
scalestyleNamed stops along a design scale (e.g. spacing-100…spacing-900)
motionstyleNamed animation/transition presets with duration, easing, and purpose
principlestyleGuiding 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.

ResourceDescription
Full SpecComplete schema reference for every field and constraint
Interactive SamplesSide-by-side JSON ↔ rendered documentation for real-world entities
JSON SchemaThe raw .schema.json files — use for editor autocompletion
Example FilesComplete, valid example documents for every entity and guideline type
GitHub DiscussionsAsk questions, share ideas, propose changes

Getting started recipe:

  1. Copy the minimal document above
  2. Replace the example entities with your own design system's components and tokens
  3. Add documentBlocks entries to each entity as your docs grow
  4. Validate with npm run validate to catch schema errors early

Design System Documentation Standard (DSDS) 0.1 — Draft Specification

GitHub