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 — guidelines, anatomy, API specs, variants, states, accessibility, examples, design specifications, principles, scales, motion definitions, content, and interactions — lives in a unified document block system. Each document block entry is a typed container identified by a kind discriminator.
The goal is simple: make design system documentation structured, portable, and consumable by tools — whether that tool is 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 with 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 those tokens — and the components, styles, and patterns that use them — should be understood and applied.
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.
spec/
├── dsds-spec.md # Complete specification (single source of truth)
├── schema/
│ ├── dsds.schema.json # Root JSON Schema
│ ├── dsds.bundled.schema.json # Auto-generated single-file bundle
│ ├── common/ # Shared primitives
│ │ ├── example.schema.json # example
│ │ ├── 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
│ ├── 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
│ ├── content.schema.json # content, contentLabelEntry, localizationEntry
│ ├── design-specifications.schema.json # designSpecifications, spacingSpec, sizingSpec, typographySpec, etc.
│ ├── 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
├── build-samples.js # Generates the interactive sample viewer from example JSON
├── build-quickstart.js # Generates the quick start guide from minimal examples
└── 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)
Start with spec/dsds-spec.md — it is the single source of truth for the entire specification, covering document structure, entity types, all guideline types, links, status, rich text, use cases, extensions, and naming conventions.
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 the schema in your DSDS files for editor support:
{
"$schema": "./spec/schema/dsds.schema.json",
"dsdsVersion": "0.1",
"documentation": [
{
"name": "My Design System",
"components": [
{
"kind": "component",
"name": "my-component",
"displayName": "My Component",
"description": "A brief description.",
"status": { "status": "draft" }
}
]
}
]
}npm run build
# Open site/dist/index.htmlThe site is auto-generated from the schema JSON files — property tables, type descriptions, and cross-references are all derived directly from the schemas. The prose modules provide 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
}Generate a concise, standalone introduction to DSDS from the minimal example files:
npm run build-quickstartThis reads spec/examples/minimal/ and produces site/dist/quickstart.html — a single-page guide covering:
- Document structure —
dsdsVersion, documentation groups, and the items array - Entity types — all six kinds with descriptions and common properties
- Guidelines system — the 13 guideline types, which entities support them, and how purpose and best-practices work
- Minimal examples — copy-pasteable starting points for every entity type, pulled live from the validated examples
- Validation — how to use the JSON Schema and CLI to validate your documents
The examples are read from disk at build time, so the guide automatically reflects any changes to spec/examples/minimal/.
A DSDS file has a dsdsVersion and a documentation array. Each entry in documentation is a named group with separate typed arrays for each entity kind: components, tokenGroups, themes, styles, patterns. All arrays are optional.
Three optional top-level properties describe the design system as a whole:
extends (optional) — declares that this document extends another DSDS document — typically a core design system. Identifies the base system by name, optional URL, and optional version. See Systems of Systems: Extends.
purpose (optional) — describes what the design system is for, who it serves, and when teams should or should not adopt it. Contains a description and an array of useCases with positive and negative scenarios.
bestPractices (optional) — system-level best practices that apply across the entire design system. These are cross-cutting rules like "always use semantic tokens" or "test all components at 200% zoom" — not component-specific guidance (which lives in each entity's documentBlocks array). Each entry pairs an actionable guidance statement with a rationale and an enforcement kind.
System-level vs. entity-level: The root
purposeandbestPracticesapply to the design system as a whole. They are distinct from the entity-levelpurposeandguidelinedocument block types that appear inside each entity'sdocumentBlocksarray.
{
"dsdsVersion": "0.1",
"purpose": {
"description": "A unified component library for all Acme product teams.",
"useCases": [
{ "description": "Building new product UIs on the Acme platform.", "kind": "positive" },
{
"description": "One-off marketing landing pages with heavy custom art direction.",
"kind": "negative",
"alternative": {
"name": "marketing-toolkit",
"rationale": "The marketing toolkit provides art-direction-first primitives."
}
}
]
},
"bestPractices": [
{
"guidance": "Always use semantic tokens instead of raw color values.",
"rationale": "Semantic tokens ensure themes apply correctly across all surfaces.",
"kind": "required",
"category": "development"
},
{
"guidance": "Test all components at 200% browser zoom.",
"rationale": "WCAG 1.4.4 requires content to be functional at 200% zoom.",
"kind": "required",
"category": "accessibility",
"criteria": [
{ "url": "https://www.w3.org/TR/WCAG22/#resize-text", "label": "1.4.4 Resize Text" }
]
},
{
"guidance": "Do not override token values at the component level.",
"rationale": "Overrides break theme consistency and make audits unreliable.",
"kind": "prohibited",
"category": "development"
}
],
"documentation": [
{
"name": "Acme Design System",
"components": [
{ "kind": "component", "name": "button", "..." }
],
"tokenGroups": [
{ "kind": "token-group", "name": "color-palette", "..." }
],
"themes": [
{ "kind": "theme", "name": "dark", "..." }
],
"styles": [
{ "kind": "style", "name": "spacing", "..." }
],
"patterns": [
{ "kind": "pattern", "name": "error-messaging", "..." }
]
}
]
}Each entity kind lives in its own named array within a documentation group. The array name is the primary type indicator. Every entity still carries a kind discriminator for use in contexts where the source array is not available, along with common identity properties (name, displayName, description, status) and a documentBlocks array for all structured documentation.
kind value |
Entity | Array | Description |
|---|---|---|---|
"component" |
Component | components |
A reusable UI component |
"token" |
Token | (inline in token groups) | A single design token |
"token-group" |
Token Group | tokenGroups |
A hierarchical group of related tokens (recursive) |
"theme" |
Theme | themes |
A named set of token overrides (lists token names, not values) |
"style" |
Style | styles |
A macro-level visual style |
"pattern" |
Pattern | patterns |
A broad interaction pattern |
Every entity accepts an optional agents object providing context optimized for AI/LLM consumption. Human-readable content like documentBlocks is written for people; agents is written for machines.
| Property | Type | Description |
|---|---|---|
intent |
string |
One sentence stating the primary purpose. |
constraints |
array |
Hard rules with must/must-not/should/should-not levels. Each entry has rule, level, and optional context. |
disambiguation |
array |
Confusion-resolution entries against similar entities. Each has entity (name) and distinction (the deciding criterion). |
antiPatterns |
array |
Known incorrect uses with corrective alternatives. Each has description and instead. |
examples |
array |
Ready-to-use code examples. Each has description, code, and optional language. |
keywords |
string[] |
Semantic retrieval terms and synonyms. |
{
"agents": {
"intent": "Trigger a user action within the current view.",
"constraints": [
{ "rule": "Do not use for page navigation.", "level": "must-not" }
],
"disambiguation": [
{ "entity": "link", "distinction": "Use button for actions; use link for navigation." }
],
"keywords": ["action", "submit", "click", "CTA"]
}
}Document blocks also accept the same optional agents object. Block-level agent context is scoped to that specific section — for example, an anatomy block's agents might disambiguate part naming, while a guidelines block's agents might provide enforcement-level constraints for AI code generation:
{
"documentBlocks": [
{
"kind": "guideline",
"items": ["..."],
"agents": {
"intent": "Enforce correct Button usage in generated UI code.",
"constraints": [
{ "rule": "Never place two primary buttons on the same surface.", "level": "must-not" }
],
"keywords": ["button rules", "best practices", "usage guidelines"]
}
}
]
}Every entity carries a status property that accepts either a plain string for the common case or a full object when platform-specific tracking is needed:
{ "status": "stable" }When per-platform readiness is needed, use the object form with overall and platforms:
{
"status": {
"overall": "stable",
"platforms": {
"react": { "status": "stable", "since": "1.0.0" },
"ios": { "status": "experimental", "since": "3.0.0" },
"figma": { "status": "stable", "since": "1.0.0" }
}
}
}The object form requires platforms — if you don't need platform-specific tracking, use the string form. When overall is "deprecated", a deprecationNotice is required.
All structured documentation lives in the documentBlocks array on each entity. Each document block entry is a typed container with a kind discriminator. Entity types accept only the document block types relevant to them through scoped unions:
| Scope | Used by | Specific types | General types (all entities) |
|---|---|---|---|
| Component | component | anatomy, api, events, variants, states, design-specifications | guideline, purpose, accessibility, content |
| Style | style | principles, scale, motion | (same) |
| Pattern | pattern | interactions, events, anatomy, variants, states | (same) |
| Token | token, token-group, theme | (none) | (same) |
| Kind value | Container | Items | Description |
|---|---|---|---|
"guideline" |
items |
guidelineEntry | Actionable usage rules with rationale and enforcement levels |
"purpose" |
useCases |
useCase | When to use and when not to use the entity |
"accessibility" |
Named arrays | various | Keyboard, ARIA, screen reader, contrast, motion specs |
"content" |
labels, localization |
contentLabelEntry, localizationEntry | Content guidelines and i18n considerations |
"anatomy" |
parts |
anatomyEntry | Component visual structure with token references |
"api" |
Named arrays | various | Props, events, slots, CSS hooks, methods |
"events" |
items |
eventEntry | Component events with payloads, DOM behavior, and lifecycle |
"variants" |
items |
flagVariant | enumVariant | Dimensions of visual/behavioral variation |
"states" |
items |
stateEntry | Interactive states with token overrides |
"design-specifications" |
properties + variants / sizes / states |
various | Design properties, spacing, sizing, typography, responsive — grouped by variant, size, and state |
"principles" |
items |
principleEntry | High-level guiding beliefs |
"scale" |
steps |
scaleStep | Ordered token value progressions |
"motion" |
items |
motionEntry | Named easing curves with durations and usage |
"interactions" |
items |
interactionEntry | Pattern flow steps |
Every document block type accepts an optional agents property — the same agents object available on entities. Block-level agents provide context scoped to that specific documentation section (e.g., constraints specific to accessibility requirements, or disambiguation relevant only to the API surface).
Document block types follow two naming patterns:
- Plural names for homogeneous lists:
"variants","states","principles","interactions" - Singular names for self-contained structures:
"guideline","scale","anatomy","api","accessibility","design-specifications","purpose","content","motion"
DSDS separates two kinds of guidance:
- Purpose provides concrete scenarios for when to use and when not to use an entity. Each use case carries a
kind("positive"or"negative") and negative entries recommend an alternative with a rationale. - Guidelines provide concrete rules for using an entity correctly after you've chosen it. Each rule pairs an actionable
guidancestatement with arationaleexplaining why.
{
"documentBlocks": [
{
"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."
}
}
]
},
{
"kind": "guideline",
"items": [
{
"guidance": "Limit each surface to one primary button.",
"rationale": "Multiple primary buttons dilute visual hierarchy.",
"kind": "required",
"category": "visual-design"
}
]
}
]
}The kind property on each guideline entry classifies how strictly it should be followed. Defaults to "informational" when omitted.
| Value | RFC 2119 | Meaning |
|---|---|---|
"required" |
MUST | Non-compliance is a defect. |
"encouraged" |
SHOULD | Follow in most cases; exceptions need justification. |
"informational" |
MAY | Advisory context with no enforcement. (default) |
"discouraged" |
SHOULD NOT | Avoid unless justified. |
"prohibited" |
MUST NOT | Violations are defects. |
Any guideline can reference external standards via the criteria property:
{
"guidance": "Button label text must meet a minimum 4.5:1 contrast ratio.",
"rationale": "Text contrast ensures readability for users with low vision.",
"kind": "required",
"category": "accessibility",
"criteria": [
{
"url": "https://www.w3.org/TR/WCAG22/#contrast-minimum",
"label": "1.4.3 Contrast (Minimum)"
}
]
}Component variants are modeled as dimensions of variation inside a "variants" guideline. Each dimension is either a flag (a boolean toggle that is on or off) or an enum (a set of mutually exclusive values):
{
"kind": "variants",
"items": [
{
"kind": "enum",
"name": "emphasis",
"displayName": "Emphasis",
"description": "Controls the visual weight of the button.",
"values": [
{ "name": "primary", "description": "High-emphasis — the main action." },
{ "name": "secondary", "description": "Medium-emphasis — important but not primary." },
{ "name": "ghost", "description": "Low-emphasis — tertiary actions." }
]
},
{
"kind": "flag",
"name": "full-width",
"displayName": "Full Width",
"description": "Stretches the button to fill its container.",
"purpose": "Provides a prominent call to action in narrow or single-column layouts."
}
]
}An enum variant (type: "enum") has a values array with at least two entries — use it for dimensions like size (sm/md/lg) or emphasis (primary/secondary/ghost). A flag variant (type: "flag") has no values array — the component either has the flag active or it doesn't. Use it for binary capabilities like disabled, full-width, or icon-only. Both types accept an optional purpose field explaining why the variation exists.
Every example requires a presentation or a value (or both). Presentations are visual or interactive demonstrations. Four media types are supported:
type |
What it shows |
|---|---|
"image" |
Screenshot, diagram, annotated mockup |
"video" |
Screen recording, animation, walkthrough |
"code" |
Source code snippet with language metadata |
"url" |
Link to any web resource (Storybook, CodeSandbox, etc.) |
{
"type": "examples",
"items": [
{
"title": "Primary button in default state",
"presentation": {
"kind": "image",
"url": "https://design.acme.com/assets/button-primary.png",
"alt": "A primary button with a blue background and white label text 'Save'."
}
}
]
}The "design-specifications" guideline documents measurable visual specs — design properties, spacing, sizing, typography, and responsive behavior. The base properties map defines the default configuration — an open map of design property names to values. Values are always strings: either design token names (e.g., "button-primary-bg", "space-4") or raw CSS values (e.g., "#0055b3", "16px", "transparent"). Systems that do not use tokens simply provide raw values directly.
The variants, sizes, and states arrays each contain named entries with their own properties maps. Each entry is self-contained — it represents that condition's complete set of values, not an override of the base. For example, a "danger" variant entry carries its own token names (like "button-danger-bg") or raw values, independent of the base properties. The variantStates array handles variant×state combinations (e.g., primary+hover) where the visual treatment differs across variants, with each entry specifying both a variant and a state alongside its properties.
{
"kind": "design-specifications",
"properties": {
"background": "button-primary-bg",
"color": "button-primary-text",
"border-radius": "4px",
"border-color": "transparent"
},
"spacing": {
"internal": { "icon-to-label": "space-2", "container-horizontal": "space-4" }
},
"variants": [
{
"name": "danger",
"properties": {
"background": "button-danger-bg",
"color": "#ffffff",
"border-color": "transparent"
}
}
],
"sizes": [
{
"name": "small",
"properties": {
"font-size": "14px"
},
"spacing": {
"internal": { "icon-to-label": "4px", "container-horizontal": "space-3" }
}
}
]
}DSDS does not carry token values or platform API mappings. The W3C Design Tokens Format (DTCG) file is the single source of truth for resolved values and platform-specific identifiers. Use the source property on a token entity to link it to its DTCG definition:
{
"type": "token",
"name": "color.text.primary",
"tokenType": "color",
"source": "./tokens.json"
}Most entity types enforce ^[a-z][a-z0-9-]*$ on the name property. Tokens and token groups are the intentional exception — their names are unconstrained to accommodate DTCG and design tool naming conventions that use dots (color.text.primary), slashes (color/text/primary), or other separators.
The links array on each entity handles both external resources and entity relationships via a kind discriminator:
{
"links": [
{
"kind": "source",
"url": "https://code.acme.com/design-system/src/button/button.tsx",
"label": "React component source"
},
{
"kind": "alternative",
"url": "https://design.acme.com/components/link",
"label": "Link component (alternative)"
}
]
}Standard external types: source, design, storybook, documentation, package, repository. Standard relationship types: alternative, parent, child, related. Custom types are permitted.
Tool-specific internal identifiers go in $extensions using namespaced keys. Extensions are available on the root document, on each documentation group, and on each entity:
{
"$extensions": {
"com.designTool": { "componentId": "abc123def456" },
"com.storybook": { "storyId": "components-button--primary" }
}
}Rule of thumb: If it's a URL a human would click, it belongs in links. If it's an internal identifier consumed programmatically by a specific tool, it belongs in $extensions.
Large organizations often maintain a core design system shared across the company and one or more extension systems that layer product-specific components, tokens, and guidelines on top of it. The extends mechanism makes this relationship explicit at two levels.
The root extends property declares that the entire document inherits from a base DSDS document. It names the core system, optionally provides a URL to the base document, and records the version being extended:
{
"dsdsVersion": "0.1",
"extends": {
"system": "Acme Core Design System",
"url": "https://design.acme.com/v2/core.dsds.json",
"version": "2.0.0",
"description": "Enterprise extension layering admin components and stricter a11y rules on the core system."
},
"documentation": [ "..." ]
}Individual components and tokens can declare that they extend a specific base entity from the parent system. The entity-level extends includes a name (matching the base entity), an optional system override, and an optional modifications array that serves as a human-readable changelog:
{
"kind": "component",
"name": "button",
"extends": {
"name": "button",
"description": "Adds an 'enterprise' variant and a 'theme' prop.",
"modifications": [
{ "type": "added", "target": "variant:enterprise", "description": "High-emphasis enterprise brand variant." },
{ "type": "added", "target": "prop:theme", "description": "'default' | 'admin' sub-brand switcher." },
{ "type": "inherited", "target": "guideline:anatomy", "description": "Anatomy inherited from core without changes." }
]
},
"displayName": "Button",
"description": "Enterprise Button — extends core with an enterprise variant and theme prop.",
"status": "stable",
"documentBlocks": [ "..." ]
}The extends declarations establish the relationship between a base system and its extensions. Merge and resolution semantics — which guidelines are inherited, which are overridden, which are appended — are the responsibility of consuming tooling, not the schema. DSDS provides a portable, machine-readable way to declare these relationships; tools decide how to resolve them.
Example file: See
examples/extension-system.dsds.jsonfor a complete enterprise extension system demonstrating document-level extends, entity-level extends on both components and tokens, themodificationschangelog, and net-new entities that exist only in the extension.
Several optional properties declare default values via the JSON Schema default keyword. Validators do not inject these — they are advisory hints for tools and consumers that indicate what value to assume when the property is omitted.
| Property | Schema | Default | Meaning when omitted |
|---|---|---|---|
guidelineEntry.kind |
guideline.schema.json |
"informational" |
The guideline is advisory context with no enforcement expectation. |
link.required |
link.schema.json |
false |
The linked artifact is an optional enhancement, not a dependency. |
anatomyEntry.required |
anatomy.schema.json |
false |
The anatomy part is conditionally rendered, not always present. |
apiProperty.required |
api.schema.json |
false |
The property does not need to be provided by the consumer. |
apiProperty.deprecated |
api.schema.json |
false |
The property is not deprecated. |
ariaAttribute.required |
accessibility.schema.json |
false |
The ARIA attribute is conditionally required or optional. |
richText.format |
rich-text.schema.json |
"markdown" |
Text content is interpreted as CommonMark. |
The schema is organized into three directories plus a root schema:
| Directory | Contents |
|---|---|
common/ |
Shared primitives — richText, statusObject, link, example, extensions, metadata, useCase |
entities/ |
Entity types — component, token (+ tokenGroup), theme, style, pattern |
document-blocks/ |
Document block types — 13 type schemas + scoped unions (componentDocumentBlock, styleDocumentBlock, patternDocumentBlock, tokenDocumentBlock) |
The root dsds.schema.json defines the document structure and references entity schemas via a oneOf discriminated union. The dsds.bundled.schema.json is auto-generated by scripts/bundle.js for tools that require a single-file schema.
Property tables on the specification site are generated directly from the schema JSON — they are always in sync with the schema and cannot drift from the implementation.
- 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.