The two contracts
helix-ui only has two hard contracts. Every other convention is negotiable; these aren’t.
1. Tokens are JSON, not code
The canonical token source is W3C DTCG JSON at
packages/tokens/tokens/*.json. CSS variables and TypeScript types are
build outputs, not the source of truth.
If you’re adding a token:
- Edit the relevant DTCG JSON file (
color.json,space.json, …). - Run
pnpm build:tokens. - Commit the JSON edit only. Generated CSS/TS is rebuilt by CI.
If you find yourself editing a generated file directly, stop — you’re fighting the system. Find the upstream JSON instead.
Why JSON
DTCG JSON is parseable by any tool — Figma plugins, Style Dictionary, your own scripts. helix-ui’s CSS and TypeScript outputs are just one consumer. The Figma sync showcase round-trips the same JSON.
2. Every component owns a spec.md
Each component file (packages/core/src/components/<name>/<Name>.tsx) has a
sibling spec.md. Its frontmatter is a machine-readable spec; its body is
the human-readable doc.
---title: Buttonimport: "import { Button } from '@helix-ui/core'"description: 'A primary action element.'props: - { name: variant, type: '"solid" | "soft" | "ghost" | "outline"', default: '"solid"' } - { name: tone, type: '"brand" | "neutral" | "danger"', default: '"brand"' }tokens: - color.bg.action.brand.default - radius.mda11y: - inherits all <button> semantics - requires aria-label when icon-only---## Anatomy...If you’re adding or changing a component:
- Update
spec.mdin the same commit as the code change. - Keep
props,tokens, anda11yaccurate — the docs site, the LLM manifest, and the MCP server all consume this file.
Why spec.md
Three different consumers read these files:
- The Astro docs site (this site) renders them as content pages.
pnpm build:llmsflattens them intollms-full.txtfor AI ingestion.- The
@helix-ui/mcpserver exposes them as MCP resources for Claude Code, Cursor, etc.
A new component without a spec is invisible to two of those three.
3. Token discipline in authored CSS
The token contract applies to design choices in component CSS:
- Color values use
var(--helix-ui-color-*); raw hex belongs in token JSON or external-format adapters, not component styles. - Spacing declarations (
margin,padding, andgapfamilies) usevar(--helix-ui-space-*); bare non-zero pixels bypass the density gene. - Radii, fonts, shadows, and motion use their corresponding
var(--helix-ui-*)tokens.
Structural pixels are allowed when no design token is being chosen: 1px
borders, focus offsets, SVG dimensions, media query breakpoints, and documented
numeric props such as chart height or sidebar width. When you add one, make the
prop/spec clear enough that a reviewer can tell it is layout mechanics rather
than a new hidden design scale.
Where the contracts are checked
pnpm typecheck— catches missing props.pnpm build:llms— fails if a component is exported without a spec.pnpm exec stylelint 'packages/core/src/**/*.css'— catches unknown--helix-ui-*variables, raw hex in component CSS, and bare pixel spacing.- CI runs these checks on every PR.