Registry Overview

Purpose and Scope

A shadcn/ui registry is a distribution system for code. Instead of publishing only a package and asking consumers to adapt it, a registry describes concrete files, dependencies, configuration, CSS variables, and relationships between items so the shadcn CLI can copy code into a project. In first-party docs, registries are described as useful for components, hooks, pages, config, rules, and other files, and they are intentionally not limited to React. This page explains that model from the perspective of the CLI implementation: how registry content is exposed, loaded, resolved, parsed, and handed to installation workflows.

Sources: apps/v4/content/docs/registry/meta.json, packages/shadcn/src/registry/index.ts

The important terms are small but precise. A registry catalog is the root registry.json payload that gives a registry its identity and lists available items. A registry item is an installable unit, commonly represented as registry-item.json or as an item inside the catalog. An item can declare files, package dependencies, development dependencies, registry dependencies, CSS variables, and type information such as registry:block, registry:ui, registry:component, or registry:hook. A registry source is where an item is found: the built-in shadcn registry, a URL, a GitHub item address, a local file, or a configured namespaced registry.

Sources: packages/shadcn/src/registry/resolver.ts, packages/shadcn/src/registry/loader.ts

Relevant Source Files

  • apps/v4/content/docs/registry/meta.json — Defines the registry documentation section and shows the first-party docs spine: introduction, getting started, GitHub registries, registry indexes, examples, namespaces, authentication, MCP, API reference, and schema pages.
  • packages/shadcn/src/registry/index.ts — Re-exports the public registry module surface used by the CLI and other package internals, including registry lookup, item resolution, search, loading, and error types.
  • packages/shadcn/src/registry/resolver.ts — Implements runtime item resolution for install flows, including namespaced registries, GitHub addresses, URLs, local files, built-in style paths, recursive dependency fetching, parsing, and source-aware resolved item trees.
  • packages/shadcn/src/registry/loader.ts — Implements local registry loading from registry.json, include handling, validation, item source tracking, catalog creation, and single-item creation for registry build or publish workflows.

Registry Model

The docs navigation treats registries as a complete product area, not as a hidden implementation detail. The registry section includes pages for getting started, GitHub registries, registry indexes, examples, namespaces, authentication, MCP, API reference, and both root and item schema references. That organization reflects the underlying architecture: a registry is both a user-facing publishing format and a CLI-facing data source. The CLI needs enough structure to validate a catalog, find an item by name, expand registry dependencies, and rewrite file paths for the consuming project without assuming one framework or hosting platform.

Sources: apps/v4/content/docs/registry/meta.json

At the content level, the root catalog and individual item schemas give registry authors a stable contract. The root registry.json is the entry point: it names the registry, gives a homepage, and contains the item list. Each item then acts as the portable manifest for code that should be installed together. Official examples show an item with a name, type, title, description, registryDependencies, package dependencies, dev dependencies, file descriptors, and CSS variables. The resolver code reinforces that this data is not only documentation: fetched payloads are parsed through registry item schemas before they are allowed to continue into the install pipeline.

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

Public Registry API Surface

The registry package entry point intentionally gathers the useful operations into one module. It re-exports APIs for reading configured registries, obtaining registry items, resolving registry items, reading an individual registry, and reading registry indexes. It also re-exports search and loader functions, plus a broad set of typed registry errors. For a developer reading the codebase, packages/shadcn/src/registry/index.ts is the best orientation point because it tells you which internal registry capabilities are treated as package-level building blocks rather than one-off command details.

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

Exported nameRole
getRegistriesReads the configured registry collection used by CLI workflows.
getRegistryItemsRetrieves items from registry sources.
resolveRegistryItemsProduces resolved installable registry item data.
getRegistryReads a single registry.
getRegistriesIndexReads registry index data for discovery.
searchRegistriesSearches registry data.
loadRegistryLoads a local registry catalog from disk.
loadRegistryItemLoads one local registry item by name.
LoadRegistryOptionsOption shape for local registry loading.

The exported error classes are also part of the practical API contract. Registry failures are not all equivalent: a missing registry, unauthorized registry, forbidden registry, fetch failure, unconfigured namespace, local file problem, parse failure, validation failure, missing item, invalid namespace, or missing environment variable needs a different user-facing explanation. By exporting names such as RegistryUnauthorizedError, RegistryValidationError, RegistryItemNotFoundError, and RegistryInvalidNamespaceError, the registry layer gives commands and integrations a vocabulary for precise diagnostics instead of collapsing every failure into a generic fetch or parse error.

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

Resolution Flow

Resolution starts with the user’s requested item strings and the project configuration. resolveRegistryItemsFromRegistries copies the requested item list, checks whether configured registries exist, and builds URL plus header pairs for namespaced registry items. GitHub item addresses are deliberately skipped in this namespace pass because they have their own address scheme. When a configured registry contributes headers, those headers are recorded in registry context keyed by the resolved URL. The function returns strings that downstream fetchers can request directly, while preserving authentication and per-registry headers separately.

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

fetchRegistryItems is the next important stage. It creates or reuses a source cache, then resolves each item according to address type. A GitHub address is sent to the GitHub registry item fetcher. A local file is read through the local registry fetch path. A full URL is fetched directly and then parsed as a registry item. A namespaced item beginning with @ is resolved through configured registries, fetched, and parsed. Anything else falls back to the built-in shadcn registry path, using the project style from config or the default new-york-v4, producing paths like styles/new-york-v4/button.json.

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

This layered flow lets a single CLI command accept several kinds of addresses without making the command responsible for each transport. It also makes validation consistent: fetched URL items, namespaced items, and built-in items are all parsed with the same registry item schema before installation logic sees them. When parsing fails, the resolver wraps the underlying schema error in RegistryParseError with the original item identifier. That design keeps user-facing error messages connected to the input the user typed, even after the resolver has translated the input into a URL or file path.

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

Local Registry Loading and Includes

Local registry loading serves a different but related workflow: authoring, building, validating, and publishing a registry from files on disk. loadRegistry resolves options, reads the registry with includes, computes the root directory, and returns a catalog created from the loaded result. loadRegistryItem follows the same initial path but searches the loaded registry’s items by name and throws RegistryItemNotFoundError if the requested item is absent. These functions are the source-backed bridge between registry authoring files and the JSON payloads that can later be served or consumed.

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

The include system is designed for larger registries that do not want a single enormous catalog file. readRegistryWithIncludes reads and parses the root file, validates the root registry, and builds source maps that remember which registry file and directory produced each item. If the root registry has no include entries, every item is recorded as coming from the root file and the function returns immediately. If includes are used, the root file must be named registry.json; otherwise the loader throws RegistryValidationError. After included files are read, duplicate item names are validated before the final root registry is returned without the include field.

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

That source tracking matters because registry item file paths are relative to where the item was authored, not necessarily where the final catalog is emitted. createRegistryCatalog maps every item through path rewriting and strips file content so the catalog remains an index rather than a bundle of file bodies. createRegistryItem performs the item-focused version of the same rewrite process for a single installable item. The result is a clean separation: a catalog helps clients discover items, while an item payload contains the detailed file data needed to install one selected unit.

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

System-to-Code Mapping

ConceptCode locationImplementation signal
Registry docs sectionapps/v4/content/docs/registry/meta.jsonLists the documentation pages that define the public registry learning path.
Public module surfacepackages/shadcn/src/registry/index.tsRe-exports lookup, search, resolution, loading, and typed errors.
Configured namespace resolutionpackages/shadcn/src/registry/resolver.tsConverts configured registry item names into URLs and header context.
Address-type fetchingpackages/shadcn/src/registry/resolver.tsHandles GitHub, local file, URL, namespaced, and built-in style item addresses.
Local authoring loaderpackages/shadcn/src/registry/loader.tsReads registry.json, validates includes, tracks item sources, and creates catalogs or item payloads.

The key design pattern is that registry resolution is source-aware but command-agnostic. The resolver does not need to know whether an item will be installed from an add command, previewed in a registry workflow, or processed as a dependency of another item. It receives item identifiers and config, normalizes them into fetchable sources, validates the returned payloads, and preserves enough metadata for later dependency and file handling. The loader mirrors that pattern for local files: it reads authoring-time structure, validates it, and returns normalized registry data that later tools can consume.

Sources: packages/shadcn/src/registry/resolver.ts, packages/shadcn/src/registry/loader.ts

Practical Next Steps

If you are consuming registry items, start by identifying which address form you are using. Plain names target the built-in shadcn registry for the configured style. Full URLs fetch item JSON directly. Local file paths support authoring and testing. GitHub item addresses use the GitHub path. Namespaced names such as @acme/button require matching components.json registry configuration so the resolver can build the URL and headers. That distinction is the most useful debugging handle when an item cannot be found, cannot authenticate, or parses as the wrong shape.

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

If you are building a registry, treat registry.json as the catalog and registry item manifests as the install contract. Keep item names unique, use schema-backed fields, and decide whether your registry is small enough for a single file or should use includes. When includes are necessary, make the root file registry.json and expect the loader to validate duplicate items and rewrite paths based on item source locations. From here, read the focused pages on registry schema, registry indexes, namespaces, authentication, and build-and-publish workflows for the specific task you are implementing.

Sources: packages/shadcn/src/registry/loader.ts, apps/v4/content/docs/registry/meta.json