Authoring a reskinnable-demo skin
This app hosts one skin-agnostic shell (src/shell/) that renders one
skin per URL segment /[skin]/.... A skin is a domain plugin living entirely
under src/skins/<id>/. Its ONLY inbound dependency is the frozen Skin
contract in src/shell/skin-contract.ts — that is what lets skins be authored
in isolation without touching shared code.
To add a skin you (1) map the demo beats it must hit, (2) implement the Skin
contract in src/skins/<id>/, (3) put its server-only agent in
src/skins/<id>/agent.ts, and (4) register both — the client skin in
src/shell/registry.ts and the agent in src/shell/agent-registry.ts, keyed by
the identical id.
Before writing anything, re-open
src/shell/skin-contract.ts(the source of truth) and read the shipped skins as worked references (ls src/skins/is the registered set — do not memorise a count). They are good at different things; demo-beats.md § "Which skin to copy for what" is the routing table. The short version: every registered skin butbookstoreis demo-complete, so nearly any of them is a fair end-to-end reference, and what you pick …