Guide
Getting started
Create or clone, prerequisites, your first component, and a tour of the repo.
This guide takes you from nothing to a running docs site with your own scope. You can let npx create-bht-component-registry set the repo up, or clone this repo and do the three renames by hand. Either way you end with a pnpm workspace whose registry/ folder is the registry, a docs site at apps/docs, and a registry.config.json naming your scope.
Prerequisites
- Node 22 or newer.
- pnpm. The repo pins its version in
package.json#packageManager;corepack enablemakespnpmresolve to it. - git.
- For publishing later: an npm account and an org for your scope. See Scopes.
No environment variables are needed to develop, build or deploy. Tokens are only involved when you publish. See Publishing.
Create a registry
1npx create-bht-component-registry my-registry
The command prompts for:
- Scope (required): your npm scope without the
@, for exampleacme. It must be lowercase, DNS-label-like (a-z,0-9,-) and not a reserved word. - npm registry: where
pnpm releasepublishes. Defaulthttps://registry.npmjs.org; GitHub Packages ishttps://npm.pkg.github.com; a private registry is whatever URL it gives you. - Starter categories: which
registry/<scope>/<category>folders to create.
It then writes registry.config.json, renames the example scope to yours, runs pnpm install and a first pnpm build, and prints the next steps.
1cd my-registry2pnpm dev
Open http://localhost:3000.
Or clone this repo
1git clone https://github.com/behivetech/bht-component-registry.git my-registry2cd my-registry3pnpm install
Then make the repo yours:
- Set
scopeinregistry.config.json(and thesite.title,site.url,site.descriptionandsite.linkswhile you are there). - Rename
registry/exampletoregistry/<your-scope>, and editregistry/<your-scope>/scope.json(name,tagline). - In each component's
package.json, change@example/to@<your-scope>/innameandrepository.directory. Do the same in eachREADME.mdimport line andCHANGELOG.mdheading. - Remove the
@example/*entries fromapps/docs/package.json#dependencies; the catalog step re-adds your renamed packages on the next run. - Run
pnpm install, thenpnpm dev.
You can also delete registry/example entirely and scaffold your first component with pnpm gen; the site's chrome does not depend on the example content.
Your first component
1pnpm gen component acme atoms button2pnpm install3pnpm dev
pnpm gen writes registry/acme/atoms/button/; the catalog step adds @acme/atoms.button to the docs app's dependencies, which is why pnpm install follows. Components explains every file it created and the conventions that drive the docs.
Repo tour
my-registry/
├─ apps/docs/ the docs site (Next.js, static export to apps/docs/out)
│ ├─ default-docs/ the template's guide pages (a same-path file under docs/ overrides one)
│ ├─ scripts/generate-catalog.ts builds the catalog before dev and build
│ ├─ src/app/(site)/ home, [scope], [scope]/[category]/[name]/<tab>, tokens, not-found
│ ├─ src/components/docs/ live examples, markdown, props table, catalog cards
│ ├─ src/lib/catalog/ typed access to the generated catalog, README/CHANGELOG parsing
│ └─ e2e/ Playwright specs against the static build
├─ docs/ your pages for the site's Docs section (never touched by update)
├─ packages/
│ ├─ env/ shared tsup config and the bht-registry-docgen bin
│ ├─ class-names/ getClassName() used by the component template
│ ├─ scope/ scope slug validation (reserved names, format)
│ ├─ eslint-config/, typescript-config/
│ └─ create-bht-component-registry/ the npx create and update CLI
├─ registry/<scope>/
│ ├─ scope.json name, tagline, visibility, optional tokens path
│ └─ <category>/<name>/ one npm package per component
├─ plopfile.ts pnpm gen — loads scripts/generators/* and generators/*
├─ scripts/generators/ the template's generators (component, doc, generator)
├─ generators/ your own generators; update never touches them
├─ .changeset/ Changesets config and pending changesets
├─ .github/workflows/ ci.yml (verify + e2e), release.yml (changesets publish)
├─ registry.config.json scope, npmRegistry, templateVersion, site branding
├─ template.manifest.json the paths `update` is allowed to replace
├─ Dockerfile, nginx.conf serve apps/docs/out from a container
└─ pnpm-workspace.yaml, package.json, vitest.config.ts
Workspace-only packages use the @bht-component-registry/* scope and are never published. Anything public is bht-prefixed so it collides with nothing of yours.
Commands
All run from the repo root.
| Command | What it does |
|---|---|
pnpm dev | Regenerates the catalog, then Next dev on :3000 |
pnpm build | Builds every package, then the static export to apps/docs/out |
pnpm serve | Serves apps/docs/out on :3000 the way a static host would |
pnpm verify | build, then lint + types + unit tests for every package |
pnpm test:e2e | Playwright against the static build (builds first) |
pnpm gen | Pick a generator; pnpm gen component <scope> <category> <name> skips the prompts. See Generators |
pnpm changeset | Record a change for the next release |
pnpm version-packages | Apply pending changesets: bump versions, write CHANGELOGs |
pnpm release | Build the registry packages and changeset publish to npmRegistry |