Build and Publish Registries

Purpose and Scope

A shadcn registry is a distribution point for code: components, hooks, utilities, pages, config, rules, and other files that the CLI can install into a project. The build-and-publish workflow turns a source registry definition into installable registry item payloads, then lets you serve those payloads from any host that can return JSON. The official getting-started guide frames the only hard requirement clearly: the registry catalog and each registry item must conform to the schema specifications, while the hosting technology can be Next.js, Vite, Vue, Svelte, PHP, a public GitHub repository, or another system that serves JSON over HTTP.

Sources: apps/v4/content/docs/registry/getting-started.mdx

The most important mental model is that source authoring and published consumption are separate phases. Authors work in a project that contains a root registry file and the referenced source files. The builder reads that registry file, resolves each item, deduplicates repeated file paths and dependencies, annotates each item with the registry item schema URL, and emits JSON into an output directory. Consumers do not need your build-time project layout; they need a stable endpoint where the root catalog and item payloads can be fetched. That separation is what makes the registry portable across different application frameworks.

Sources: packages/shadcn/src/commands/registry/build.ts, apps/v4/content/docs/registry/getting-started.mdx

Relevant Source Files

  • apps/v4/content/docs/registry/getting-started.mdx - Defines the reader-facing registry setup model, the role of the root registry file, schema conformance requirements, hosting expectations, and single-file versus included registry structures.
  • packages/shadcn/src/commands/registry/build.ts - Implements the experimental registry build command, command options, preflight checks, schema parsing, item resolution, deduplication, and build output behavior.
  • packages/shadcn/src/commands/registry/validate.ts - Implements registry validation as a CLI command, including local registry paths, GitHub registry sources, validation reporting, diagnostics grouping, and nonzero exit behavior for invalid registries.
  • packages/shadcn/src/registry/builder.ts - Builds registry item request URLs and headers from configured registries, including built-in fallback behavior, named registries, style placeholders, environment variable expansion, query parameters, and authentication-style headers.

Authoring Model

Every registry begins with a root catalog. In the docs, that catalog is the entry point containing the registry name, homepage, and the array of items present in the registry. A minimal item names the distributable unit, declares its registry type, gives human-readable metadata, and lists files with their paths and registry file types. Larger registries can keep a root catalog and compose additional nested catalogs through include files, which keeps component, hook, and block areas independently maintainable without changing the public idea that the registry has one endpoint.

Sources: apps/v4/content/docs/registry/getting-started.mdx

That authoring model is deliberately not tied to React-only projects. The official docs say the registry can be backed by any framework as long as it serves JSON, and the repository README positions shadcn/ui as open code that can be customized and used to build a component library. For registry publishers, that means the shadcn-specific contract is the shape of the catalog and item JSON, not the web server. A GitHub repository can become a registry by adding the root catalog, while a purpose-built app can generate and serve the same payloads from a public directory.

Sources: apps/v4/content/docs/registry/getting-started.mdx

Build Command Flow

The build command is registered as a Commander command named registry:build. It accepts an optional registry file path, defaults that argument to ./registry.json, supports --output for the destination directory with a default of ./public/r, accepts --cwd for the working directory, and exposes a verbose flag. The action resolves the current working directory before calling the internal build function, so command behavior is anchored to an explicit project root rather than whichever process path happens to be active.

Sources: packages/shadcn/src/commands/registry/build.ts

Before doing useful work, the builder validates its own options and runs registry preflight checks in parallel with project information detection. The build requires a components configuration file and project info; if either is missing, it prints a message telling the user to run initialization and exits. It also fails early when the registry file cannot be found. These checks matter because registry item files often need the same alias, style, and project metadata that normal shadcn installs use, so the builder treats missing local configuration as a publish-blocking setup problem rather than as a recoverable warning.

Sources: packages/shadcn/src/commands/registry/build.ts

After preflight, the builder reads the resolved registry file, parses the JSON, and validates the catalog against the registry schema. A schema failure stops the build before any item payloads are generated. When validation succeeds, the command starts a build spinner and recursively resolves registry items using the parsed catalog, project configuration, and project information. It then removes duplicate file entries with the same path and duplicate dependency strings. This cleanup step is important for composed registries because repeated dependencies can appear naturally when an item depends on another item that references overlapping files.

Sources: packages/shadcn/src/commands/registry/build.ts

Validate Before Publishing

Validation is the safety gate to run before exposing a registry to users. The validate command is named validate, describes itself as validating a shadcn registry, and accepts a registry address argument that defaults to ./registry.json. Its argument description is broader than the build command: it supports local registry paths and GitHub sources. The command resolves the working directory, tries to resolve a GitHub validation source when applicable, starts a validation spinner, then delegates either to GitHub-specific validation or the normal local registry validator.

Sources: packages/shadcn/src/commands/registry/validate.ts

The validation report is designed for both humans and automation. When the registry is valid, the command succeeds, prints a count of checked registry files and items, and lists the registry file paths. When invalid, it fails the spinner, prints the same stats, groups diagnostics by registry file, and formats each diagnostic with contextual details such as item index, item name, include path, and file path when those details exist. The command sets a failing process exit code for invalid reports, which makes it suitable for CI gates before publishing a registry update.

Sources: packages/shadcn/src/commands/registry/validate.ts

Publishing and Consumption Mechanics

Publishing is intentionally simple once build and validation pass. Put the generated JSON output somewhere that clients can reach, commonly under a public directory such as the build command default output, then deploy the site or repository. The root endpoint must expose the registry catalog, and item endpoints must expose registry item JSON. Because the docs allow any server that can return JSON, the publish step can be a framework deployment, a static file host, or a GitHub-backed registry layout, as long as the resulting files remain reachable and schema-compliant.

Sources: apps/v4/content/docs/registry/getting-started.mdx, packages/shadcn/src/commands/registry/build.ts

The consumer-side URL builder explains how configured registries become fetchable item addresses. Given a requested item name, it parses an optional registry prefix and item segment. If the request is already a URL, local file, local path, or GitHub item address, it returns null so that direct addresses can be handled outside named registry resolution. Otherwise, it defaults unprefixed items to the built-in shadcn registry, merges built-in registries with project-defined registries, validates the selected registry configuration, and returns the final URL plus any request headers.

Sources: packages/shadcn/src/registry/builder.ts

Registry configuration can be a simple URL template or an object with a URL, parameters, and headers. The builder replaces the item name placeholder, applies the project style placeholder when available, expands environment variables, appends nonempty query parameters, and omits headers whose expanded values are blank. This behavior supports practical publishing setups such as private registries protected by tokens, style-aware endpoints, and registry URLs configured through deployment environment variables. It also means publishers should document the expected environment variables for their consumers when a registry requires authenticated or parameterized access.

Sources: packages/shadcn/src/registry/builder.ts

Command Reference

Use the build command when you are ready to produce registry JSON from a source registry definition.

shadcn registry:build ./registry.json --output ./public/r --cwd .

Use the validate command before publishing, in local development, and in CI. The default target is the root registry file in the current working directory.

shadcn validate ./registry.json --cwd .
CommandPurposeImportant inputsFailure behavior
registry:build [registry]Builds registry item JSON from a source catalog.Registry file path, output directory, working directory, verbose flag.Exits when configuration, project info, registry file, or schema parsing fails.
validate [registry]Validates a local registry path or GitHub registry source.Registry address and working directory.Prints grouped diagnostics and sets a failing exit code when the report is invalid.

A practical release flow starts by editing the root catalog and referenced files, then running validation locally. If validation reports include or item context, fix the source catalog before building because the build command also performs schema parsing and preflight checks. Next, run the build command into the directory your app or static host serves. Review the emitted item payloads for expected files, dependencies, and metadata. Finally, deploy the generated JSON and run validation again against the published or GitHub source when your release process supports it.

Sources: packages/shadcn/src/commands/registry/build.ts, packages/shadcn/src/commands/registry/validate.ts

For CI, treat registry validation as a required check and registry build as a reproducibility check. The repository-level scripts show that registry generation can be combined with formatting and test flows, while the validate command already exposes machine-friendly success and failure through its exit status. A failing validation report should block publication because consumers experience registry mistakes as install-time failures. A successful build should be archived or deployed exactly from the output directory so the files users fetch match the source catalog that passed validation.

Sources: packages/shadcn/src/commands/registry/build.ts, packages/shadcn/src/commands/registry/validate.ts

Next Steps

After this page, read the registry schema reference to understand every catalog and item field, then read the registry index and namespace pages if you need larger composed registries or multiple named sources. If your registry is private, pair this workflow with the authentication guidance and the builder behavior described here so consumers know which environment variables, headers, and query parameters must be configured before installation.