Using design-system.json
design-system.json is the same content as design-system.md, in a shape a script can parse without natural-language tricks. Reach for it when you're writing tooling.
The shape
interface DesignSystemJson {
name: string // library name
generatedAt: string // ISO timestamp
tokens: {
primitive: DesignToken[]
semantic: DesignToken[]
shadcn: DesignToken[]
}
principles: LayoutPrinciple[]
designRules: DesignRules
}
Token, principle, and rules shapes are documented in Reference → Schemas.
When to use the JSON instead of the Markdown
| Use case | Pick |
|---|---|
| Feeding context to an AI agent | design-system.md |
| Documenting for humans | design-system.md |
| Reading from a Node script | design-system.json |
| Writing a custom lint rule | design-system.json |
| Validating that a built page matches the system | design-system.json |
| Round-tripping back into Tostada | the library JSON via importLibrary (different file — see re-importing) |
Example — a build-time lint
// scripts/lint-tokens.mjs
import ds from './design-system.json' assert { type: 'json' }
const allowed = new Set(ds.tokens.shadcn.map(t => t.id))
const usedInCode = scanCodebaseForCssVars() // your scanner
for (const used of usedInCode) {
if (!allowed.has(used)) {
console.error(`Unknown shadcn token: ${used}`)
process.exitCode = 1
}
}
Example — a Figma sync (future)
const ds = await fetch('/design-system.json').then(r => r.json())
await figma.applyTokens(ds.tokens.primitive.map(t => ({ name: t.name, value: t.value })))
We don't ship a Figma sync today — but design-system.json is the shape it would consume.
Versioning
The shape evolves with Tostada. Two rules:
- Existing fields don't change meaning. A field that meant "the resolved hex color" yesterday still means that today.
- New fields are additive. If your reader doesn't know about a new field, it should ignore it.
There's no version field yet. The roadmap will introduce one before the shape changes in a breaking way.
Stability
The JSON is deterministic — same library state produces the same bytes. Diff two exports across time and you see real changes, not whitespace.