Extending the Manifest
Each packages/react/src/<Name>/ folder includes <Name>.manifest.ts, exporting <Name>Manifest. Aggregation validates the entries against ComponentSchema and emits dist/manifest.json (the complete contract with recipe sources) and dist/components.json (the lean companion for agents). Both carry the version of @operator-ds/react, which aggregation reads from its package.json.
Add a component
- Author the entry as
Record<string, Component>(see any existing*.manifest.ts). - Re-export it through the package barrel.
- Run
pnpm buildthenpnpm --filter @operator-ds/manifest run sync-check— it fails loud on a folder whose<Name>Manifestexport is missing or has no<Name>entry, an orphan manifest export, duplicate names, a stale entry (content that no longer matches the built package, such as an old enum value), a built package whose exports no longer match its manifest sources (compared by content, so runpnpm buildafter editing one; touching a file changes nothing), or schema violations.
Add its guidance
The manifest says what a component accepts. packages/manifest/scripts/guidance.mjs says when to choose it, and the installer's index, search and instruction block are built from that file. Add an entry for the component:
use_for: one or two short phrases for the need it answers, the way a person would ask for it ("show a status label"). A part that only lives inside another component takespart_ofinstead.not_for: needs that look like this component's and belong to another, each with the component to use.values: for an option prop the manifest does not describe, a note on what each value is for.
Aggregation fails when a component has no entry, when a note names a value its prop does not take or misses one it does, and when an undescribed option prop has no notes. The result ships as dist/guidance.json.
Schema
Use ComponentSchema / PropSchema and the exported Component / Manifest types from @operator-ds/manifest. Enum values must match the component variants. A mode-dependent union lists its types and describes which mode accepts each shape.
Keep props in step with the component
A test compares each entry's props and enum values with the TypeScript props of the component it documents. It fails on a prop the component declares (or takes from a library) that the manifest omits, a manifest prop the component no longer has, enum values that differ, and an example that passes an undocumented prop. Disagreements that exist today are listed with their owning batch in packages/manifest/scripts/parity-known.json; remove an entry from that list when you correct the manifest or the component.
Add or update a recipe
- Keep the runnable recipe source under
apps/docs/components/, using relative imports for local helpers. Import core components by name from@operator-ds/react. - Register it in
packages/manifest/scripts/patterns.mjswith a description, source path, canonical locallayout, andcomposed_ofcore component names. Include core components used by its local dependencies, and only those:composed_ofmust name exactly the components the recipe's files import from@operator-ds/react(by name; a namespace import is rejected). Add the recipe wherever the list is kept (apps/docs/lib/product-patterns.ts, the examples route map, the patternsmeta.jsonand docs page); a test names each place that disagrees. - Render the same source on its MDX page and add
<PatternEntry pattern="RecipeName" />. This reads the generated manifest for canonical usage and complete source panels. - Build the manifest and React packages, then run the manifest
aggregate,test,sync-check, andverifyscripts. Aggregation resolves relative imports recursively and includes exact file contents and package dependencies inpatterns.
Aggregation rejects missing sources, outside paths, aliases and unknown or undeclared core references. Recipes retain local imports and remain application source, not core React exports.
PatternSchema keeps its original description, composed_of, and layout fields. Optional files and dependencies allow older manifests to remain valid. files maps safe relative TypeScript paths to complete source text, while dependencies lists imported package names.