Composition contracts
Every shipped design component declares a compose contract (site/src/components/compose-contract.ts): a leaf ({ tier: 'leaf' }) or a container with named slots ({ slots: { name: { accepts, required } } }), plus an optional owns list of the raw facsimile tags it legitimately implements as its own primitive.
scripts/compose-graph.ts reads those contracts and the real JSX composition graph (via the TypeScript compiler) and emits the map below. It replaces the old hand-maintained dependency doc. It is derived from code, so it can never drift out of date, and the gate (bun run compose:graph) fails on any violation:
raw-facsimile: a component renders a raw<button>/<input>/<a href>/<hr>/[role=…]it does notown. Compose the real primitive instead.off-accepts-child: a container is slotted with a design component not in its slot’saccepts.required-slot-unfilled: a required slot left empty at a usage site.missing-contract: a shipped component with nocomposedeclaration.
This is what makes “demos use real components” a permanent, enforced invariant rather than a manual audit.
Violations
✓ No violations: every container composes real, approved children.
Composition map
Tier is derived from the contract (leaf / optional / required). owns = raw facsimile tags a component legitimately implements as its own primitive. Slots show name: accepts (∗ = any design component, ✳ = required).
| Component | Hier | Tier | Owns | Slots | Renders | Consumers |
|---|---|---|---|---|---|---|
| Accordion | composite | optional | none | default: ∗ · headerAccessory: ∗ | none | none |
| AgentMessage | composite | optional | none | default: ∗ | none | none |
| AppShell | pattern | leaf | none | 1 | none | |
| Avatar | primitive | leaf | button | none | none | |
| Badge | primitive | leaf | none | none | none | |
| Banner | composite | leaf | none | none | none | |
| BarChart | primitive | leaf | none | none | none | |
| BottomSheet | composite | required | none | default: ∗ ✳ · footer: ∗ | none | none |
| BrandMark | primitive | leaf | none | 2 | none | |
| Breadcrumbs | composite | leaf | none | none | none | |
| Button | primitive | leaf | button | none | none | |
| Calendar | behavior | leaf | button | none | 1 | |
| Callout | composite | leaf | none | none | none | |
| Card | primitive | optional | none | default: ∗ | none | none |
| Chart | composite | leaf | none | none | none | |
| ChatBubble | composite | optional | button | default: ∗ | none | 2 |
| Checkbox | primitive | leaf | input | none | none | |
| Chip | primitive | leaf | button | none | none | |
| CircularProgress | primitive | leaf | role=progressbar | none | none | |
| ClusterGrid | pattern | required | none | default: NockerlNodeCell ✳ | none | none |
| CodeBlock | composite | leaf | none | none | none | |
| Combobox | composite | leaf | input | none | none | |
| CommandPalette | pattern | leaf | input | none | none | |
| ContextGauge | composite | leaf | none | none | none | |
| DatePicker | composite | leaf | button | 1 | none | |
| DefinitionTrigger | primitive | leaf | button | none | none | |
| Dialog | composite | required | none | default: ∗ ✳ | none | none |
| DiffViewer | composite | leaf | none | none | none | |
| Divider | primitive | leaf | hr | none | none | |
| Drawer | composite | required | none | default: ∗ ✳ · footer: NockerlButton/NockerlIconButton | none | none |
| EmptyState | composite | optional | none | actions: NockerlButton/NockerlIconButton | 1 | none |
| Fab | composite | leaf | button, role=menu | none | none | |
| FacetedBackground | primitive | optional | none | default: ∗ | none | none |
| Field | primitive | leaf | input, textarea | none | none | |
| FieldValidation | composite | leaf | none | none | none | |
| FileUpload | composite | leaf | none | none | none | |
| FormLayout | pattern | optional | none | default: ∗ · headerAccessory: ∗ · footer: ∗ | none | none |
| Gauge | primitive | leaf | none | none | none | |
| Icon | primitive | leaf | none | none | none | |
| IconButton | primitive | leaf | button | none | none | |
| JobRow | composite | optional | none | trailing: ∗ | none | none |
| Kbd | primitive | leaf | none | none | none | |
| KeyValue | composite | leaf | none | none | none | |
| LineChart | primitive | leaf | none | none | none | |
| Link | primitive | leaf | a | none | none | |
| List | composite | leaf | none | none | none | |
| ListboxOption | behavior | leaf | none | none | none | |
| ListItem | behavior | optional | button | details: ∗ · trailing: ∗ | none | none |
| LongPressPop | pattern | optional | none | default: ∗ | none | none |
| MarkdownContent | composite | leaf | none | none | none | |
| Menu | behavior | leaf | button, role=menu, role=menuitem | none | none | |
| MultiSelect | composite | leaf | button | 1 | none | |
| NavItem | behavior | leaf | button | none | none | |
| NockerlLockup | primitive | leaf | none | 1 | 5 | |
| NockerlLogo | primitive | leaf | none | none | 4 | |
| NodeCell | composite | optional | none | footer: ∗ | none | none |
| OtpInput | composite | leaf | input | none | none | |
| Overlay | behavior | optional | button | default: ∗ | none | none |
| PageDots | primitive | leaf | button | none | none | |
| Pagination | composite | leaf | none | none | none | |
| Panel | pattern | optional | button | default: ∗ | none | none |
| Popover | behavior | leaf | button | none | none | |
| ProgressBar | primitive | leaf | none | none | none | |
| ProgressTrack | primitive | leaf | role=progressbar | none | none | |
| RadioGroup | composite | leaf | input, role=radiogroup | none | none | |
| RecordingHud | composite | leaf | none | 1 | 1 | |
| SearchField | composite | leaf | input | none | 3 | |
| SegmentedControl | primitive | leaf | button, role=radiogroup, role=radio | none | none | |
| Select | composite | leaf | none | none | none | |
| SessionChip | composite | leaf | button | none | none | |
| SessionChipsBar | composite | required | none | default: NockerlSessionChip ✳ | none | none |
| Sidebar | pattern | leaf | none | 1 | none | |
| Skeleton | primitive | leaf | none | none | none | |
| Slider | primitive | leaf | button, role=slider | none | none | |
| Sparkline | primitive | leaf | none | none | none | |
| Spinner | primitive | leaf | none | none | none | |
| SplitButton | composite | leaf | button | none | none | |
| StatCard | composite | leaf | none | none | none | |
| StatusDisc | primitive | leaf | none | none | none | |
| StatusDot | primitive | leaf | none | none | none | |
| Stepper | composite | leaf | button | none | none | |
| Surface | primitive | optional | none | default: ∗ | none | none |
| Switch | primitive | leaf | button, role=switch | none | none | |
| Table | composite | optional | none | footer: ∗ · empty: ∗ | none | none |
| Tabs | composite | leaf | button, role=tab, role=tablist | none | none | |
| TextArea | primitive | leaf | textarea | none | none | |
| TextField | primitive | leaf | input | none | none | |
| Timeline | composite | leaf | button | none | none | |
| TimePicker | composite | leaf | button | none | none | |
| Toast | composite | leaf | none | none | none | |
| TodoWidget | composite | optional | none | headerAccessory: ∗ | none | none |
| Toolbar | pattern | optional | none | default: NockerlButton/NockerlIconButton/NockerlSegmentedControl/NockerlDivider/NockerlMenu | none | none |
| ToolCallCard | composite | leaf | none | none | none | |
| Tooltip | behavior | leaf | none | none | none | |
| TopBar | pattern | leaf | none | 3 | none | |
| Tree | composite | leaf | button | none | none | |
| Well | primitive | optional | none | default: ∗ | none | none |
| Wizard | pattern | leaf | none | none | none |