Component-driven workflow
Component-driven workflow
React Cosmos 7.4.1 is the component sandbox for packages/ui primitives.
Decision rationale:
.agents/notes/2026-09-10-component-driven-research.md.
Plan: .agents/plans/2026-09-10-component-driven-cosmos.md.
The rule
A primitive is developed in Cosmos first, then composed into a screen.
The fixture is the contract; the screen is the consumer. Verified
means: the primitive author has seen and exercised the base state AND
every other state (variants, sizes, error/disabled/loading) in Cosmos
BEFORE screen code lands. A PR that adds a primitive + screen usage in
the same commit but no fixture exercise is a defect — bounce it.
The CVA config is the variant source of truth. Map over its keys in the
fixture; do not copy-paste variant="…" strings. Kitchen-sink research
established that a stale matrix is worse than no matrix; the Cosmos
feedback loop catches the gap on the next run.
Primitive-author vs screen-author
- Primitive-author (
packages/ui/AGENTS.md): write the primitive,
update or create the fixture, run Cosmos, exercise base + each variant- dark mode. Only then commit.
- Screen-author (
apps/web/AGENTS.md): import from@brioso/ui/ui/<name>.
If the primitive does not exist (or needs a new variant/size), STOP
and switch to the primitive-author side.
Cosmos setup
cd apps/web && bunx cosmos— Vite dev server onlocalhost:5000
(or 5001 if taken). The navigation tree lists every fixture under
src/cosmos/; the controls panel exposes props so you exercise the
matrix without editing the fixture.- New fixture:
apps/web/src/cosmos/<Name>.fixture.tsx, Multi-Fixtures
format (export default { Primary: <…/>, ... }). Import the primitive
from@brioso/ui/ui/<name>(the package exports subpath) so the sandbox
exercises the built primitive, not a local copy. - Directory-tree decorator (
apps/web/src/cosmos/cosmos.decorator.tsx)
wraps every fixture in the providers it needs (TooltipProvider, theme
viaoptions.theme). For per-fixture locale, export
options: { locale, messages }from the fixture (Cosmos Fixture
Options, PR #1649).
/cosmos/<fixture> route
Dev-only, gated three ways:
sensitive-route-guard(/cosmosis inSENSITIVE_PREFIXESin
packages/auth-core/src/route-guard.ts) — request-time gate, requires
WORKER_SHARED_SECRETBearer.process.env.NODE_ENV === "production"check in the route’s server
GEThandler (mirrorsapps/web/src/routes/dev/login.ts:104).import.meta.env.DEVcheck at component render time (tree-shakes the
body out of production bundles).
The route is in iframe mode — bunx cosmos must be running alongside
vite dev. Excluded from apps/web/scripts/sync-contract.ts (no
public OpenAPI leak).
Adding a primitive
packages/ui/src/ui/<name>.tsx— CVA convention perbutton.tsx.package.json#exports— add"./ui/<name>": "./src/ui/<name>.tsx".apps/web/src/cosmos/<Name>.fixture.tsx— Multi-Fixtures, matrix
derived from CVA config.cd apps/web && bunx cosmos— exercise every variant + size + dark
mode.- Atomic commit per root
AGENTS.mdrule (one logical change).