# How the shadcn Component Registry Resolution and Fetching System Works

> Understand the shadcn component registry resolution and fetching system. Discover its three-stage pipeline for mapping names to files, resolving entries, and fetching source files with import rewriting.

- Repository: [shadcn-ui/ui](https://github.com/shadcn-ui/ui)
- Tags: internals
- Published: 2026-02-26

---

**The shadcn component registry resolution system operates through a three-stage pipeline that maps component names to implementation files by selecting the correct style or base index, resolving the component entry, and fetching source files through an LRU cache with automated import rewriting and path normalization.**

The shadcn UI monorepo implements a sophisticated component registry resolution and fetching architecture that powers both the CLI and documentation site. Located in `shadcn-ui/ui`, this system bridges the gap between abstract component names like "accordion" and the actual TypeScript source files, dependencies, and metadata required to install them in consumer projects.

## Registry Index Selection Strategy

The resolution process begins by determining which registry index contains the requested component. The shadcn component registry maintains separate indices for **styles** (e.g., `new-york-v4`) and **bases** (e.g., `radix`).

### Style vs. Base Detection

In [`apps/v4/lib/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/registry.ts), the `getIndexForStyle(styleName)` function determines whether to query a style-specific registry or a base registry. This decision relies on the `BASES` array defined in [`packages/shadcn/src/preflights/preflight-registry.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/preflights/preflight-registry.ts), which enumerates known base names.

- If the requested style starts with a recognized base prefix (e.g., `radix-vega`), the system loads the base index from [`bases/radix/_registry.ts`](https://github.com/shadcn-ui/ui/blob/main/bases/radix/_registry.ts)
- Otherwise, it loads the style index from [`styles/new-york-v4/_registry.ts`](https://github.com/shadcn-ui/ui/blob/main/styles/new-york-v4/_registry.ts) (or equivalent)

Each generated [`_registry.ts`](https://github.com/shadcn-ui/ui/blob/main/_registry.ts) file exports a plain JavaScript object conforming to the `Registry["items"]` type, serving as the runtime lookup table for component metadata.

## Component Name Resolution

Once the correct index is selected, the system resolves the specific component entry using `getRegistryComponent(name, styleName)`.

### Demo vs. Component Lookup

The resolution logic first checks if the requested name corresponds to a **demo** component using the utility in [`packages/tests/src/utils/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/tests/src/utils/registry.ts). If not found as a demo, it performs a standard lookup in the selected index via `index[key][name]`.

The returned entry contains:
- **File descriptors**: An array of objects with `path` and `type` properties
- **Dependencies**: Required packages and internal components
- **Metadata**: CSS variables, Tailwind configuration, and installation instructions

## Source File Fetching and Transformation

The `getRegistryItem(name, styleName)` function in [`apps/v4/lib/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/registry.ts) serves as the primary entry point for both the dev server and CLI. This function implements a sophisticated caching and transformation pipeline.

### LRU Caching Layer

To avoid repeated disk I/O, the system maintains an in-memory **LRU cache** (`registryCache`) that stores parsed and validated registry items. When a request arrives, the function checks this cache before proceeding to file system operations.

### Code Transformation Pipeline

For cache misses, the system performs three critical transformations on each file:

1. **Default Export Conversion**: The pipeline replaces `export default` statements with named exports (unless the file is a Next.js page), ensuring consistent import patterns in consumer projects.

2. **Import Path Fixing**: The `fixImport(content)` function rewrites internal alias imports (e.g., `@/components/...`) to maintain consistent absolute aliases, preventing broken references when components are copied into target projects.

3. **Path Normalization**: The `fixFilePaths` utility makes all file paths relative to the first file in the component and adds a `target` property specifying the destination path when the component is installed.

After transformation, the item undergoes **Zod schema validation** before storage in the LRU cache and return to the caller.

## Remote Registry Support

Beyond the core registry, the system supports third-party component registries through a global directory mechanism.

### Registry Discovery

The file [`apps/v4/registry/directory.json`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/directory.json) enumerates external registries (such as `@8bitcn` and `@clerk`). The `useSearchRegistry` hook in [`apps/v4/hooks/use-search-registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/hooks/use-search-registry.ts) consumes this JSON, implementing case-insensitive filtering to enable CLI discovery of community components.

This allows the `shadcn@latest add` command to resolve and fetch components from the broader ecosystem, not just the official registry.

## Code Examples

### Fetching a Component Programmatically

```typescript
import { getRegistryItem } from '@/lib/registry';

/**
 * Retrieve the full registry entry for the `accordion` component
 * using the `new-york-v4` style.
 */
async function loadAccordion() {
  const item = await getRegistryItem('accordion', 'new-york-v4');
  if (!item) throw new Error('Component not found');

  // `item.files` now contains the source of each file,
  // with absolute content and a `target` path ready for copy‑paste.
  console.log(item.files[0].content); // → TypeScript source of ui/accordion.tsx
}

```

### Searching Remote Registries

```tsx
import { useSearchRegistry } from '@/hooks/use-search-registry';

export function RegistrySearch() {
  const { query, setQuery, registries } = useSearchRegistry();

  return (
    <>
      <input
        placeholder="Search registries…"
        value={query}
        onChange={e => setQuery(e.target.value)}
      />
      <ul>
        {registries.map(r => (
          <li key={r.name}>
            {r.name} – {r.description}
          </li>
        ))}
      </ul>
    </>
  );
}

```

## Summary

- **Index Selection**: The `getIndexForStyle` function in [`apps/v4/lib/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/registry.ts) routes requests to either style-specific indices ([`styles/new-york-v4/_registry.ts`](https://github.com/shadcn-ui/ui/blob/main/styles/new-york-v4/_registry.ts)) or base indices ([`bases/radix/_registry.ts`](https://github.com/shadcn-ui/ui/blob/main/bases/radix/_registry.ts)) based on the `BASES` array in [`packages/shadcn/src/preflights/preflight-registry.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/preflights/preflight-registry.ts).

- **Component Resolution**: `getRegistryComponent` checks for demo components first, then performs a keyed lookup in the selected registry index to retrieve file descriptors and metadata.

- **Caching and Transformation**: `getRegistryItem` implements an LRU cache (`registryCache`) and applies `fixImport` for alias normalization, default-export conversion, and `fixFilePaths` for target path generation before Zod validation.

- **Extensibility**: The system supports third-party registries via [`apps/v4/registry/directory.json`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/directory.json) and the `useSearchRegistry` hook, enabling the CLI to discover external components.

## Frequently Asked Questions

### How does shadcn determine whether to use a style index or base index?

The `getIndexForStyle` function checks if the requested style name starts with any entry in the `BASES` array (defined in [`packages/shadcn/src/preflights/preflight-registry.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/preflights/preflight-registry.ts)). If it matches a known base prefix like `radix`, the system loads the base registry from `bases/[name]/_registry.ts`; otherwise, it loads the style-specific registry from `styles/[name]/_registry.ts`.

### What transformations are applied to component files before they are returned?

The system applies three main transformations: **default-export conversion** (replacing `export default` with named exports), **import fixing** (normalizing `@/components/...` aliases via `fixImport`), and **path normalization** (making paths relative and adding `target` destinations via `fixFilePaths`). All transformations occur in [`apps/v4/lib/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/registry.ts).

### Where does the shadcn CLI cache registry data to avoid repeated file reads?

The dev server and CLI use an in-memory **LRU cache** named `registryCache` implemented in [`apps/v4/lib/registry.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/registry.ts). This cache stores parsed and validated `RegistryItem` objects, ensuring that subsequent requests for the same component and style combination return instantly without disk I/O.

### Can the shadcn registry system fetch components from external sources?

Yes. The system supports third-party registries through a global directory file at [`apps/v4/registry/directory.json`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/directory.json), which lists community registries like `@8bitcn` and `@clerk`. The `useSearchRegistry` hook filters this list for the CLI, allowing `shadcn add` to resolve and install components from outside the official repository.