SurfaceComponentScaffoldGen
Scaffold a Clef Surface headless component $ARGUMENTS with widget FSM, anatomy parts, machine implementation, and suite manifest.
When to use: Use when creating a new Clef Surface headless component. Generates a complete component scaffold including widget specification (FSM), anatomy definition (parts contract), machine implementation, and suite manifest.
Design Principles
- Behavior-Rendering Separation: Widget specs define behavior (states, transitions, guards). Rendering is handled by framework adapters. They agree only on part names (anatomy).
- Finite State Machine Discipline: Every component is a finite state machine with explicit states, events, transitions, and guards. No implicit state.
- Anatomy Contract: The anatomy defines named parts (root, trigger, content, etc.) that both the machine and renderer reference. This is the only coupling point.
- Props API via connect(): The machine's connect() action transforms internal state into framework-neutral props objects — one per anatomy part.
Step-by-Step Process
Step 1: Register Generator
Self-register with PluginRegistry so KindSystem can track ComponentConfig → CoifComponent transformations. Registration is also handled automatically by register-generator-kinds.sync.
Examples: Register the component scaffold generator
const result = await surfaceComponentScaffoldGenHandler.register({}, storage);
Step 2: Preview Changes
Dry-run the generation using Emitter content-addressing to classify each output file as new, changed, or unchanged. No files are written.
Arguments: $0 name (string), $1 parts (string[]), $2 states (string[]), $3 events (string[])
Step 3: Generate Clef Surface Component
Generate a complete Clef Surface component scaffold with widget concept , anatomy concept , machine implementation , and suite manifest
Arguments: $0 name (string), $1 parts (string[]), $2 states (string[]), $3 events (string[])
Checklist:
- [ ] Component name is PascalCase?
- [ ] Parts list defines all structural elements?
- [ ] States define all machine states?
- [ ] Events define all transitions?
- [ ] Anatomy lists all parts and slots?
- [ ] Machine implementation has spawn, send, connect, destroy actions?
- [ ] All files written through Emitter (not directly to disk)?
- [ ] Source provenance attached to each file?
- [ ] Generation step recorded in GenerationPlan?
- [ ] Suite manifest declares dependencies on surface-core and surface-component?
- [ ] Has purpose block?
- [ ] State machine has an [initial] state?
- [ ] All states are reachable?
- [ ] ARIA role is specified?
- [ ] Keyboard bindings cover Enter, Escape, Arrow keys?
- [ ] Focus management (trap, roving, initial) is defined?
- [ ] Props have types and defaults?
Examples: Generate a dialog component
clef scaffold component --name Dialog --parts root,trigger,content --states closed,open
Generate a tabs component
clef scaffold component --name Tabs --parts root,list,trigger,content,indicator --states idle,focused,selected --events focus,select,blur
Step 4: Edit the Widget Specification
Refine the generated widget spec: adjust anatomy parts, state machine transitions, accessibility roles, and prop connections.
References
Supporting Materials
Quick Reference
| Input | Type | Purpose | |-------|------|---------| | name | String | PascalCase component name | | parts | list String | Anatomy part names (root, trigger, content, etc.) | | slots | list String | Named slot insertion points | | states | list String | FSM state names | | events | list String | FSM event names | | a11y | { role, ariaProps } | Accessibility configuration |
Output Files:
| File | Purpose |
|------|---------|
| {name}-widget.concept | Widget FSM specification |
| {name}-anatomy.concept | Parts contract definition |
| suite.yaml | Kit manifest with dependencies |
| {name}-machine.handler.ts | Machine handler implementation |
Anti-Patterns
Rendering logic in widget spec
Widget spec includes CSS, HTML, or framework-specific code — violates behavior-rendering separation.
Bad:
widget Dialog {
render {
<div class="dialog-overlay"> # HTML in spec!
<div class="dialog-content">...</div>
</div>
}
}
Good:
widget Dialog {
anatomy {
part root # Just names — rendering
part backdrop # is the adapter's job
part content
}
}
Implicit state transitions
Component changes state without explicit events — makes behavior unpredictable.
Bad:
machine {
state open {
# Implicitly closes after 5 seconds — not declarative!
after 5000ms -> closed
}
}
Good:
machine {
state open {
on close -> closed
on timeout -> closed # Explicit event
}
}
Validation
Generate a Clef Surface component scaffold:
npx tsx cli/src/index.ts scaffold component --name Dialog --parts root,trigger,content --states closed,open
Run scaffold generator tests:
npx vitest run tests/scaffold-generators.test.ts
Related Skills
| Skill | When to Use |
| --- | --- |
| /surface-theme-scaffold | Generate themes to style the component |
| /concept-scaffold | Generate concept specs for custom component concepts |
| /suite-scaffold | Generate suite manifests for component libraries |
Scan to join WeChat group