Repository navigation
Architecture
Everything the registry publishes is derived from one input: the meta.json
sidecar next to each component. One command regenerates all of it.
npm run registry:buildregistry:build runs these in order, and the order matters — later scripts
read earlier scripts' output:
| Step | Script | Writes |
|---|---|---|
| 1 | scripts/build-index.ts |
registry/index.tsx — the lazy demo map, derived from the folder structure (a folder is only registered if it has a demo.tsx). |
| 2 | scripts/build-registry.ts |
registry.json from the meta.json sidecars, then shells out to npx shadcn build, which writes public/r/<name>.json. |
| 3 | scripts/build-llms.ts |
public/llms.txt, public/llms-full.txt. |
| 4 | scripts/build-autoplay.ts |
lib/autoplay.generated.json, lib/card-frame.generated.json. |
| 5 | scripts/build-contributors.ts |
lib/contributors.generated.json (slug to GitHub login, from git history). |
| 6 | scripts/build-posters.ts |
poster frames under public/posters. |
| 7 | scripts/build-mcp-snapshot.ts |
mcp/data/registry-snapshot.json. Requires registry.json and public/llms-full.txt to already exist, and throws naming the missing one if run standalone. |
| 8 | scripts/build-readme.ts |
rewrites the counts inside README.md, in place. |
| 9 | scripts/build-status.ts |
lib/status.generated.json. Runs last because it measures the output of the steps above; running it earlier measures a stale build. |
| 10 | cli/scripts/build-cli-snapshot.mjs |
cli/data/registry-index.json, assembled from registry.json + public/llms.txt. |
The chain runs automatically before dev, typecheck, verify and build
(predev / pretypecheck / preverify in package.json, and build is
literally registry:build && next build). A fresh clone needs no extra step.
registry.json, everything under public/r/, public/llms*.txt,
lib/*.generated.json, registry/index.tsx, mcp/data/**, cli/data/** and
the marker spans in README.md are all build output. Editing them does
nothing durable: the next build overwrites the edit. A change belongs in the
source it was generated from — usually a meta.json sidecar, occasionally the
component source (prop signatures are scanned out of component.tsx), or the
generator script itself.
scripts/test-source-invariants.ts scans only app/**, lib/** and
registry/** for exactly this reason: a finding in build output is the same
finding reported twice.
Most generated files are gitignored, because every branch that adds a
component regenerates all of them, so committing them guarantees merge
conflicts in files nobody wrote. registry/index.tsx was the historical worst
case — it used to be hand-maintained, one line per component.
Two exceptions, verified against .gitignore and git ls-files:
-
registry.jsonis committed. The generator is deterministic (a sorted sidecar scan, no timestamps), so regenerating it produces no diff. It is committed because automated registry-directory discovery scans public repos for that filename. -
lib/component-order.jsonis committed and is deliberately not in theregistry:buildchain. It is derived from git history, and a Vercel shallow clone cannot be trusted to produce it, so it is a committed snapshot regenerated by hand withnpm run order:build.build-registry.tsprints a warning naming every component missing from it; a missing entry sorts that component last under the catalog's "Newest" view instead of first.
public/llms.txt and public/llms-full.txt are gitignored, despite
AGENTS.md currently saying otherwise. .gitignore lists both and
git ls-files returns neither.
build-registry.ts warns rather than fails in two places, both annotated in
the source:
- A
meta.jsonwhosenamedoes not match its folder.build-registry.tskeys items bymeta.namewhilebuild-index.tskeys demos by folder name, so a mismatch ships an installable/r/<name>.jsonwhose preview has no demo — installable but unpreviewable. - A component missing from
lib/component-order.json.
Both are warnings so an in-flight batch is not blocked. The first carries an explicit upgrade note to become a hard failure once the tree is clean.
lib/registry-origin.ts is the single source of the public origin, read by
both the build scripts and the client-side showcase, so install commands in
llms.txt, registry.json and the site can never disagree. It defaults to
https://design.helpmarq.com and is overridable with
NEXT_PUBLIC_REGISTRY_ORIGIN. The default is a real default rather than an
env-only value on purpose: the env var is only set on Vercel, so a fallback
pointing anywhere else would bake the wrong URL into every artifact built off
platform. It also trims and treats an empty string as unset.
-
registry.json/public/r/**— the shadcn CLI, and any tool that expects a standard shadcn registry index. -
public/llms.txt— one fetch returns the whole catalog as plain text.llms-full.txtadds the hand-written behavioural description per component. -
mcp/data/registry-snapshot.json— baked into the published MCP package, because once installed from npm the server has no repo to read. Regenerated bymcp/'s ownprepackbefore every publish. Tools:search_components,list_components,get_component,list_categories,install_command,get_conventions. -
cli/data/registry-index.json— the CLI's offline fallback when it cannot reach the network and has no usable cache. CLI-owned: it readsregistry.jsonandpublic/llms.txtdirectly and does not depend onmcp/in any way.