Register a catalog
One object, keyed by component name.createVendo reads it as catalog, and <VendoProvider> reads the same object as components.
vendo.ts
descriptionis selection guidance. Say what the component shows and when to reach for it.propsvalidates at render and derives the model-facing JSON Schema. One schema, never two.examplesare JSON prop objects the model copies from, and they draw the console’s preview.
What a screen may name
A name outside these two sets fails the save. It never renders as an empty box.
Accordion is the one Kit name a generated screen may not reach for, because its panels arrive as element-valued props. Tabs takes its panels as children, so it stays available.
Two names people look for are deliberately absent.
DataTable is the only table, and it sorts, filters, searches, paginates, resolves dot-path keys, and formats each cell.There is no Skeleton either. A loading placeholder is chrome the renderer paints while an app streams in.What vendo sync captures
Two artifacts, both deterministic and byte-stable. Commit them.
catalog.json is what your components are called. .vendo/components/ is what they are.
.vendo/catalog.json records what your components are called: the module that exports each one, its JSON Schema props, its description, and its examples. Rescans preserve description and example copy you edited by hand.
.vendo/components/<Name>.json records what they are. It holds no source of its own, only the module that declares the component, the binding to render, a content hash, and references.
Every byte lives beside it in .vendo/components/modules/<hex>.json as { source, imports? }, keyed by the sha-256 of its own content. A format-currency.ts that ten components import is stored once and referenced ten times.
Where the walk stops
The import walk follows your own code to closure, with no depth limit. It stops at exactly two lines.- The package boundary. Anything resolving into
node_modulesis never captured, because it is not your code. - A byte budget. 256 KB of source per component, counting the whole closure.
The bundled
zod is a shim, not zod. It resolves the declaration surface so your module loads, which is all a registry’s props: schema needs.It does not validate. .parse() and .safeParse() throw a named ZodShimError rather than returning a plausible wrong value.When a component cannot be captured
Sync never goes quiet. The record on disk carries a machine-readableskipped.reason plus a sentence you can read.
A component that could not be read at all this run is a different case. Sync leaves the previous capture exactly as it was and moves on.
How a preview draws
A preview has no data plane, so every query resolves to an empty list. Sync solves that from things you have already written, resolving a seed down three rungs.1
Your examples
The first
examples string that parses to a JSON object wins. A human’s example is real product data, and it reads better than anything Vendo could invent.2
Generated from your props schema
Values synthesized from the schema: typed correctly, respecting enums,
min, max, string formats, and optionality. Plausible rather than pretty.3
An honest label
With neither, the capture records
noSampleProps with a reason. The component still renders in your product, and previews as a labeled placeholder..vendo/components/ never churns.
Examples and generated values both travel with the capture. Treat them as you would any other value that crosses the wire, and use realistic but non-sensitive data.
Sending the corpus to Cloud
Sync offers to push the corpus so the console can render your components instead of grey placeholders. It asks once per project and commits the answer to.vendo/cloud.json.
.vendo/cloud.json
--push-components or --no-push-components. A non-interactive run with no saved answer and no flag pushes nothing and says so.
The push is cheap by construction. Component records carry references rather than source, so listing them is the hash manifest, and one keys-only call answers which module bodies the console already has.
Where to go next
Import & fork
Let a user fork one of your components and make it theirs.
In-client venue & approvals
Approve a version and it runs as real code in your page.