A standard, machine-readable format for design system documentation.
DSDS defines a JSON-based format for documenting the six entity types of a design system:
- Components — Anatomy, API, variants, states, design specifications, best practices, accessibility, content
- Tokens — Semantic meaning, platform mappings, contrast ratios, usage rules
- Token Groups — Hierarchical organization of tokens into families and sub-families
- Themes — Named sets of token value overrides for color modes, density, brand variants
- Styles — Foundations for color, typography, spacing, elevation, motion, and content — with principles, scales, motion definitions, and best practices
- Patterns — Broad interaction patterns like navigation, error messaging, and empty states — with anatomy, variants, states, interactions, and content
All structured documentation lives in a unified document block system. Each entry is a typed container identified by a kind tag. The kinds cover guidelines, anatomy, API specs, variants, states, accessibility, examples, design specifications, principles, scales, motion, content, and interactions.
The goal is simple: make design system documentation structured, portable, and consumable by tools. The tool can be a documentation site, a linter, a code assistant, or a human reading JSON.
Design system documentation today is trapped in tools. It lives in Notion, Storybook, Zeroheight, Confluence, or custom-built sites. Each has its own structure, its own conventions, and no interoperability between them.
This creates real problems:
- Migration is expensive. Switching documentation tools means restructuring everything from scratch.
- Consistency is accidental. Without a shared structure, every team invents its own format. Consumers must relearn what to expect every time.
- Tooling can't help. Tools can't reliably consume documentation from other tools because there's no shared schema to build against.
- AI needs structure. LLMs and code assistants work dramatically better with structured, predictable documentation than with ad hoc prose.
DSDS addresses these problems by defining a standard format that is:
| Quality | What it means |
|---|---|
| Structured | Every section has a defined shape. Consumers know what to expect. |
| Machine-readable | Tools can parse, generate, validate, and transform documentation. |
| Portable | Documentation is decoupled from any specific tool or platform. |
| Extensible | Vendor metadata can be added without breaking interoperability. |
| Complementary | Works alongside the W3C Design Tokens Format, not against it. |
The W3C Design Tokens Community Group defines a format for exchanging token values between tools. DSDS defines a format for exchanging the documentation that describes how to understand and apply those tokens, plus the components, styles, and patterns that use them.
The two formats are designed to work together. DSDS does not duplicate token values or platform identifiers. The W3C Design Tokens Format file is the source of truth for values. Use the source property on a token entity to link it back to its DTCG definition.
The authoritative reference for every schema, field, and document-block type is the documentation site at designsystemdocspec.org. Property tables there are generated directly from the schema JSON — they cannot drift from the implementation.
Start here:
- Overview — What DSDS is, the entity model, and how the pieces fit together.
- Quick Start — Document structure, entity kinds, the document-block system, and minimal examples for every entity type.
- Schema Architecture — The full schema reference. Covers document structure, entity types, the
agentsproperty, status, the document-block system, links, extends, extensions, naming conventions, and conformance levels, all with live property tables sourced from the schema. - Interactive Samples — Side-by-side JSON ↔ rendered docs for real-world entities (component, token, theme, style, pattern).
Per-schema reference pages live alongside the narrative pages — e.g. entities/component, document-blocks/guideline, common/agents. Every page is auto-generated from its corresponding spec/schema/**/*.schema.json file.
The site can also be built locally for offline browsing or while developing the spec — run npm run build and open site/dist/index.html.
This README intentionally does not duplicate schema field listings, document-block type catalogs, default values, enforcement levels, or example payloads. Those live on the documentation site as a single source of truth.
spec/
├── schema/
│ ├── dsds.schema.json # Root JSON Schema
│ ├── dsds.bundled.schema.json # Auto-generated single-file bundle
│ ├── common/ # Shared primitives
│ │ ├── agent-collection.schema.json # agentCollection (multi-entity agent context file)
│ │ ├── agents.schema.json # agents (agent context for AI/LLM consumption)
│ │ ├── example.schema.json # example
│ │ ├── extends.schema.json # documentExtends, entityExtends
│ │ ├── extensions.schema.json # $extensions
│ │ ├── link.schema.json # link
│ │ ├── system-metadata.schema.json # systemMetadata
│ │ ├── rich-text.schema.json # richText
│ │ ├── presentation.schema.json # presentationImage, presentationVideo, presentationCode, presentationUrl
│ │ ├── status.schema.json # status, statusObject, statusValue, platformStatus
│ │ └── purpose.schema.json # purpose, useCase
│ ├── metadata/ # Modular entity metadata kinds (entityMetadata union)
│ │ ├── metadata.schema.json # entityMetadata (oneOf union of every metadata kind)
│ │ ├── aliases.schema.json # aliasesMetadata
│ │ ├── category.schema.json # categoryMetadata
│ │ ├── description.schema.json # descriptionMetadata
│ │ ├── extends.schema.json # extendsMetadata
│ │ ├── last-updated.schema.json # lastUpdatedMetadata
│ │ ├── links.schema.json # linksMetadata
│ │ ├── preview.schema.json # previewMetadata
│ │ ├── since.schema.json # sinceMetadata
│ │ ├── status.schema.json # statusMetadata
│ │ ├── summary.schema.json # summaryMetadata
│ │ ├── tags.schema.json # tagsMetadata
│ │ └── thumbnail.schema.json # thumbnailMetadata
│ ├── entities/ # Entity types
│ │ ├── component.schema.json # component
│ │ ├── pattern.schema.json # pattern
│ │ ├── style.schema.json # style
│ │ ├── theme.schema.json # theme, tokenOverride
│ │ └── token.schema.json # token, tokenGroup
│ └── document-blocks/ # Document block types
│ ├── document-blocks.schema.json # Scoped unions (componentDocumentBlock, styleDocumentBlock, etc.)
│ ├── accessibility.schema.json # accessibility, keyboardInteraction, ariaAttribute, colorContrast
│ ├── anatomy.schema.json # anatomy, anatomyEntry
│ ├── api.schema.json # api, apiProperty, apiEvent, apiSlot, etc.
│ ├── guideline.schema.json # guideline, guidelineEntry, criterionReference, criterionDefinition
│ ├── content.schema.json # content, contentLabelEntry, localizationEntry
│ ├── design-specifications.schema.json # designSpecifications, spacingSpec, sizingSpec, typographySpec, etc.
│ ├── events.schema.json # events, eventEntry
│ ├── import.schema.json # import, importEntry
│ ├── interaction.schema.json # interactions, interactionEntry
│ ├── motion.schema.json # motion, motionEntry, motionDuration
│ ├── principle.schema.json # principles, principleEntry
│ ├── scale.schema.json # scale, scaleStep
│ ├── state.schema.json # states, stateEntry
│ └── variant.schema.json # variants, flagVariant, enumVariant, variantValue
└── examples/
├── starter-kit.dsds.json # Complete document with components, tokens, styles, patterns
├── minimal/ # Lightweight examples showing the floor of documentation
├── common/ # Per-definition examples for common primitives
├── entities/ # Per-definition examples for entity types (incl. empty-state pattern)
└── document-blocks/ # Per-definition examples for document block types (incl. motion, content)
scripts/
├── bundle.js # Generates dsds.bundled.schema.json from split schemas
├── validate.js # Validates all example files against the bundled schema
├── sync-examples.js # Syncs markdown dsds:include directives with example JSON
├── build-site.js # Generates the static specification site (orchestrator)
├── build-samples.js # Generates the interactive sample viewer from example JSON
├── render-entity.js # Server-side entity rendering used by build-samples.js
├── render-prop-table.js # Shared schema-to-HTML property table renderer (used by build-site + MDX)
├── compile-mdx.mjs # MDX content compiler for narrative pages (overview, quickstart, schema-architecture)
├── nav.js # Shared navigation builder for spec pages
└── visualize.js # Generates schema architecture diagram (SVG + Mermaid)
site/
├── tokens.css # Centralized design tokens (colors, fonts, spacing, radii, etc.)
├── style.css # Core site stylesheet (layout, nav, typography — imports tokens.css)
├── pages.css # Shared styles for standalone pages (samples, quickstart)
├── components/ # Reusable HTML web components (ES modules)
│ ├── index.js # Barrel file — imports all components, registers custom elements
│ ├── _shared.js # Shared utilities (createShadow, esc, BASE_RESET, FONT)
│ ├── badge.js # <ds-badge> — status/category badges
│ ├── back-to-top.js # <ds-back-to-top> — scroll-to-top link
│ ├── button.js # <ds-button> — button with variants and sizes
│ ├── card.js # <ds-card> — bordered content card
│ ├── code.js # <ds-code> — syntax-highlighted code (block + inline)
│ ├── cross-refs.js # <ds-cross-refs> — cross-reference links
│ ├── def-example.js # <ds-def-example> — definition example block
│ ├── def-index.js # <ds-def-index> — page-level definition index
│ ├── def-section.js # <ds-def-section> — definition section container
│ ├── footer.js # <ds-footer> — page footer
│ ├── heading.js # <ds-heading> — section heading (h1–h6) with anchor
│ ├── note.js # <ds-note> — callout/warning box
│ ├── prop-table.js # <ds-prop-table> + <ds-prop> — schema property table
│ ├── schema-header.js # <ds-schema-header> — schema page header
│ ├── scrollspy.js # <ds-scrollspy> — scroll position tracker
│ ├── sidebar.js # <ds-sidebar> — collapsible sidebar panel
│ ├── sidenav.js # <ds-sidenav> + <ds-nav-group> + <ds-nav-link>
│ ├── table.js # <ds-table> — styled table wrapper
│ ├── tabs.js # <ds-tabs> + <ds-tab> — tabbed content
│ ├── toc.js # <ds-toc> — auto-built table of contents
│ ├── toolbar.js # <ds-toolbar> — sticky top toolbar
│ └── type-ref.js # <ds-type-ref> — type reference link
├── samples-template.html # Template for the interactive sample viewer
└── dist/ # Generated HTML site (auto-generated)
Visit designsystemdocspec.org for the canonical reference, or see the Documentation section above for entry points. Property tables, type definitions, and cross-references are all rendered live from the schema.
The spec/examples/ directory contains validated example files:
starter-kit.dsds.json— A complete document with components, tokens, a style, and a pattern, showing the full architecture.minimal/— Lightweight examples (8–30 lines each) showing the floor of documentation for each entity type.entities/component.json— A full Button component with anatomy, API, variants (flag and enum types), states, design specs, best practices, purpose, and accessibility.entities/empty-state-pattern.json— An Empty State pattern demonstrating anatomy, variants, states, interactions, content guidelines, and localization on a pattern entity.entities/style.json— A Spacing style with principles, scale, motion definitions, and best practices.entities/token.json— A semantic color token with source reference, category, and guidelines.entities/token-group.json— A hierarchical color palette with nested hue families and grade scales.entities/theme.json— A dark mode theme with token overrides, purpose, best practices, and accessibility.entities/pattern.json— An error messaging pattern with interactions, component references, and accessibility.
Install dependencies and run the validation suite:
npm install
npm run validateThis runs three steps automatically: syncs example includes, bundles the schema, and validates all example files.
To validate your own DSDS file:
npx ajv validate -s spec/schema/dsds.bundled.schema.json -d my-system.dsds.jsonReference https://designsystemdocspec.org/v0.2.1/dsds.bundled.schema.json from your DSDS files via the $schema keyword to get editor autocompletion and inline validation. See the Quick Start docs page for the single-entity and multi-entity document shapes.
npm run build
# Open site/dist/index.htmlThe site is auto-generated from the schema JSON files. Property tables, type descriptions, and cross-references all come directly from the schemas. The prose modules add context and examples.
After changing any schema file, regenerate the bundled version:
npm run bundleGenerate a diagram showing how all schema files relate to each other:
npm run visualizeThis produces:
site/dist/schema-architecture.mmd— Mermaid source (renders natively on GitHub)site/dist/schema-architecture.svg— Clean SVG with no CSS, compatible with Figma
Options:
node scripts/visualize.js --format=svg # SVG only
node scripts/visualize.js --format=mmd # Mermaid source only
node scripts/visualize.js --layout=root,entities,guidelines,common # Custom column order
node scripts/visualize.js --layout=root+common,entities,guidelines # Stack groups with +
node scripts/visualize.js --no-edges # Hide dependency edgesGenerate a side-by-side documentation page that shows how DSDS JSON maps to rendered output:
npm run build-samplesThis reads example JSON files from spec/examples/ and produces site/dist/samples.html — a self-contained page with:
- Tabs for each entity type: Button Component, Color Token, Error Messaging Pattern, Spacing Style, Dark Theme
- Side-by-side layout: raw JSON on the left, rendered documentation on the right
- Element-level highlighting: hover over any rendered element to see its corresponding JSON, and vice versa
- Color-coded section bars mapping JSON sections to their visual output
- Off-screen indicators when highlighted code is scrolled out of view
To add a new example tab, add an entry to the SAMPLES array in scripts/build-samples.js:
{
file: "entities/component.json", // path relative to spec/examples/
key: "component", // top-level key to extract
id: "component", // unique tab identifier
label: "Button Component", // human-readable tab label
}Narrative content (site/content/*.mdx — the Overview, Quick Start, and Schema Architecture pages) is compiled to HTML by scripts/compile-mdx.mjs. Authors write prose alongside two custom shortcodes:
<ds-example file="..." label="..." />— inlines a JSON example fromspec/examples/minimal/as a fenced code block.<ds-prop-table schema="..." def="..." />— renders the property table for any$defsentry directly from the schema. Per-schema docs pages and narrative pages share the same renderer (scripts/render-prop-table.js), so a description change in a schema flows to every page automatically.
Example:
### Anatomy entry
A component or pattern's anatomy entry has the following shape:
<ds-prop-table schema="document-blocks/anatomy" def="anatomyEntry" />Special values:
schema="root"— loadsspec/schema/dsds.schema.json.def="$root"— renders the schema's top-levelproperties(used for schemas that don't use$defsat all).
The Quick Start page (site/content/quickstart.mdx) is compiled the same way as every other narrative page. There is no longer a separate build command for it: run npm run build and the page is regenerated at site/dist/quickstart.html.
The spec version lives in three coordinated places:
spec/schema/dsds.schema.json#/properties/dsdsVersion/const— the single source of truth. The bundle script, the nav, every page title, and the versioned dist directory all derive from this value.- The
$idURL on every schema file — e.g.,https://designsystemdocspec.org/v0.2.1/metadata/last-updated.schema.json. Every example document's$schemafield and every"dsdsVersion"literal inside example JSON has to track the same version. package.json#version— the npm package version. Conventionally kept in lockstep withdsdsVersion.const.
The scripts/bump-version.js script keeps the first two in sync across all 44 schema files, every example, the README, and the MDX content pages. package.json is handled separately because it's not a schema-consumer file.
| Change | Spec version | New URL path? | Old URL path |
|---|---|---|---|
| Schema additions (new optional fields, new union members, new entity kinds) | Bump patch (e.g. 0.2 → 0.2.1) |
Yes — published at /v0.2.1/ |
/v0.2/ stays untouched as a historical artifact |
| Breaking changes (renamed/removed fields, new required fields, tightened constraints) | Bump minor or major (e.g. 0.2.1 → 0.3) |
Yes — published at /v0.3/ |
All older versions stay untouched |
| Documentation-only edits (typos, prose clarifications, no schema or example changes) | No bump | No | No change |
The versioned dist directories (site/dist/v<n>/dsds.bundled.schema.json) are immutable public contracts. npm run build refuses to overwrite an existing one. Every consumer that pins $schema to that URL relies on the file there never changing.
This is the exact sequence for cutting a release that includes schema changes. Skip steps 1–3 for a documentation-only release.
-
Make your schema changes under
spec/schema/. Add new files, edit existing ones, or update the unions inmetadata/metadata.schema.json/document-blocks/document-blocks.schema.jsonas needed. -
Add or update examples under
spec/examples/. Per-definition example files live inspec/examples/{common,document-blocks,entities,metadata}/<schemaName>.jsonand are picked up automatically by the docs site for each schema page. Update full-document examples (starter-kit.dsds.json, etc.) and entity examples (entities/component.json, etc.) to demonstrate the new feature in context. -
Update the README project structure listing under
## Project Structureif you added or removed schema files. (The site nav auto-discovers schemas, so no MDX updates are needed for that.) -
Bump
package.json#versionto the target version (e.g.0.2.0→0.2.1). -
Add a CHANGELOG entry at the top of
CHANGELOG, mirroring the format of the prior release. Include a one-line header noting where the bundled schema is now served (e.g., "Schema files are now served athttps://designsystemdocspec.org/v0.2.1/...") and an "Additions" or "Breaking changes" section describing every schema-visible change. -
Run the version bump. Preview the change first:
node scripts/bump-version.js 0.2.1 --dry-run
Apply it:
node scripts/bump-version.js 0.2.1
This rewrites
dsdsVersion.const, the root schema title, every$idURL across the 44 split schemas, every example's$schemaURL and"dsdsVersion"literal, the README, and the MDX content pages — then regeneratesspec/schema/dsds.bundled.schema.jsonso the bundle reflects the new version. The script is drift-tolerant: it migrates any stale/v<X>/URL it finds, not just the one currently indsdsVersion.const. -
Build the site.
npm run build
This regenerates every page under
site/dist/and publishes a newsite/dist/v<new-version>/dsds.bundled.schema.json. If a versioned directory for the new version already exists with a differing bundle, the build will print a warning and skip the copy — delete the file manually and rerun the build to intentionally re-publish. -
Validate.
npm run validate
All example documents and per-definition examples must pass. A failure here usually means an example file uses an old field name or a newly required field is missing.
-
Spot-check the rendered site. Confirm the version reads correctly in three places:
- Page
<title>tags (e.g.,DSDS Last Updated Metadata — DSDS 0.2.1). - The nav title (
Design System Documentation Spec 0.2.1). - The footer (
Design System Documentation Spec (DSDS) 0.2.1 — Draft Specification).
The new schema page should exist at
site/dist/<group>-<name>.html(e.g.,site/dist/metadata-last-updated.html), and the versioned bundle should exist atsite/dist/v<new-version>/dsds.bundled.schema.json. - Page
-
Commit. Stage the schema changes, example updates, README, CHANGELOG,
package.json, and the entiresite/dist/tree (including the new versioned subdirectory) in one commit. The historical versioned subdirectories undersite/dist/v<older>/must stay untouched.
For a typo fix or prose clarification that doesn't touch any schema or example:
npm run build # regenerates HTML only; no version bump, no new versioned bundleNo changelog entry, no version bump, no new /v<n>/ artifact. Commit the regenerated HTML.
- Structure enables quality. A defined format creates a floor of quality and completeness.
- Guidance without justification is incomplete. Every best practice must answer "why?"
- Documentation should be portable. Teams change tools. Documentation should survive the transition.
- Education is a responsibility. Explain what, why, and how.
- Specificity over subjectivity. "Use sparingly" is not guidance. "Limit to one per surface" is.
- Schema is the source of truth. Property tables are generated from schema JSON, not hand-written. Prose provides context; schemas provide structure.
This is an early-stage specification (v0.1). Feedback is welcome:
- Open an issue for questions, suggestions, or problems with the spec.
- Open a PR for proposed changes to the spec, schema, or examples.
This project is open source. See LICENSE for details.