Drop-in replacement for shadcn build
, generate non-error prone registry with automatic detection of dependencies and files.
A zero-configuration
(no registry.json required), shadcn add / open in v0 compatible registry builder. With amazing visual feedback like how many dependencies and files are being added to a file/component and much more.
The best configuration is no configuration. Focus on developing building blocks, components, pages, etc rather than spending time configuring the registry.

Simplify your registry.json
by removing properties like dependencies
, devDependencies
, registryDependencies
, and files
.
If you don't need to add custom properties or extend default ones, you can even delete the registry.json
file entirely.
{
"items": [
{
"name": "dialog",
"type": "registry:ui",
- "registryDependencies": [
- "button"
- ],
- "dependencies": [
- "@radix-ui/react-dialog"
- ],
- "files": [
- {
- "path": "registry/default/ui/dialog.tsx",
- "type": "registry:ui"
- }
- ]
- }
]
}
Or delete the registry.json
file entirely. No changes will be made to the generated public/r/dialog.json
file. Smart, right?
rm registry.json && npx smart-registry
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
"dependencies": ["@radix-ui/react-dialog"],
"files": [
{
"type": "registry:ui",
"target": "components/ui/button.tsx",
"content": "...",
"path": "registry/default/ui/button.tsx"
},
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
]
}
Manual maintenance of registry.json
files can lead to errors due to missing dependencies or files, or wrongful addition of unnecessary ones. Smart Registry
reduces these risks by automating the detection and generation of the all-in-one r/registry.json
and r/<registry-item>.json
entries, making registry management more efficient.
If your project contains a registry
, components
, or src/components
directory, Smart Registry
will automatically detect and generate the necessary registry files.
For more details, refer to the directory structure section.
npx smart-registry
Yeah, that's it! You don't need to do anything else (not even registry.json). Smart Registry
has the word smart
in it for a reason.
If you want, you can customize the output directory, working directory, and provide additional files or directories to build the registry from.
Version:
[email protected]
Usage:
$ smart-registry [files/directories] ... [options]
Arguments:
files/directories files or directories to extend the registry (optional)
Options:
-o, --output <path> destination directory for json files (default: "./public/r")
-c, --cwd <cwd> the working directory (default: "./")
-i, --ignore <pattern> ignore files matching the pattern (default: none)
-u, --with-utils include @/lib/utils in the registry items if exists (default: false)
-v, --version display version
-h, --help display help
With disabled automatic detection:
-p, --patterns-only generate registry items for only given files/directories (default: false)
-r, --registry-only generate registry items for only given registry.json (default: false)
Codemods:
--codemod-radix migrate to unify "@radix-ui/react-*" imports to "radix-ui"
Cleanup:
--remove-prefix remove given prefix from the registry item names (default: none)
Author:
Neeraj Dalal <[email protected]> (https://nrjdalal.com)
e.g. to generate the registry in the json
directory from some file and directory at the working directory (apps/www
).
npx smart-registry path/to/file.ext path/to/directory ... --output json --cwd apps/www
cwd
is useful when working with monorepos or multiple projects.
Let's take the following directory structure to understand how Smart Registry
works.
registry/
└── default/
├── lib/
│ └── utils.ts
└── ui/
├── button.tsx
└── dialog.tsx
Smart Registry
will scan theregistry
directory and its sub-directories to find all the files (if noregistry
directory is found, it will scan thecomponents
orsrc/components
directory).- For each file, it will generate a
<registry-item>.json
file by reading the file's content and extracting the imports for registry dependencies, dependencies, and files recursively. - It will then generate a
registry.json
file by combining all the<registry-item>.json
files with all the properties required forshadcn add
oropen in v0
.
public/
└── r/
├── button.json
├── dialog.json
├── registry.json
└── utils.json
You can add/extend the generated public/r/registry.json
and public/r/<registry-item>.json
files by creating a registry.json
file in the root of your project. The properties in this file will be merged with the generated properties.
We will consider the dialog component with the following directory structure to demonstrate the extension of properties.
registry/
└── default/
├── lib/
│ └── utils.ts
└── ui/
└── dialog.tsx
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
"dependencies": ["@radix-ui/react-dialog"],
"files": [
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
]
}
{
"items": [
{
"name": "dialog",
"type": "registry:ui",
+ "meta": {
+ "tags": ["dialog", "modal"]
+ }
}
]
}
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
"dependencies": ["@radix-ui/react-dialog"],
"files": [
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
],
+ "meta": {
+ "tags": ["dialog", "modal"]
+ }
}
{
"items": [
{
"name": "dialog",
"type": "registry:ui",
+ "files": [
+ {
+ "type": "registry:ui",
+ "path": "registry/default/ui/button.tsx"
+ }
+ ]
}
]
}
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
"dependencies": ["@radix-ui/react-dialog"],
"files": [
+ {
+ "type": "registry:ui",
+ "target": "components/ui/button.tsx",
+ "content": "...",
+ "path": "registry/default/ui/button.tsx"
+ },
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
]
}
{
"items": [
{
"name": "dialog",
"type": "registry:ui",
+ "registryDependencies": ["button"]
}
]
}
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
"dependencies": ["@radix-ui/react-dialog"],
"files": [
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
],
+ "registryDependencies": ["button"]
}
Note: Only add the dependency that you want to specify the version for. The rest of the dependencies will be automatically added.
{
"items": [
{
"name": "dialog",
"type": "registry:ui",
+ "dependencies": ["@radix-ui/[email protected]"]
}
]
}
Generated public/r/dialog.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "dialog",
"type": "registry:ui",
- "dependencies": ["@radix-ui/react-dialog"],
+ "dependencies": ["@radix-ui/[email protected]"],
"files": [
{
"type": "registry:ui",
"target": "components/ui/dialog.tsx",
"content": "...",
"path": "registry/default/ui/dialog.tsx"
},
{
"type": "registry:lib",
"target": "lib/utils.ts",
"content": "...",
"path": "registry/default/lib/utils.ts"
}
]
}
- Use direct name for default registry.
registry/
├── blocks/
│ └── toasty.tsx
├── components/
│ └── toaster.tsx
├── hooks/
│ └── use-toast.ts
├── lib/
│ └── utils.ts
└── ui/
└── toast.tsx
- Or use
default
sub-directory for default registry.
registry/
└── default/
├── blocks/
│ └── toasty.tsx
├── components/
│ └── toaster.tsx
├── hooks/
│ └── use-toast.ts
├── lib/
│ └── utils.ts
└── ui/
└── toast.tsx
Both generate the following items in public/r
directory.
public/
└── r/
├── toasty.json name: toasty target: blocks/toasty.tsx
├── component.json name: toaster target: components/toaster.tsx
├── use-toast.json name: use-toast target: hooks/use-toast.ts
├── utils.json name: utils target: lib/utils.ts
└── toast.json name: toast target: components/ui/toast.tsx
- Use
<registry-name>
sub-directory for named registry.
registry/
├── default/
└── new-york/
├── blocks/
│ └── toasty.tsx
├── components/
│ └── toaster.tsx
├── hooks/
│ └── use-toast.ts
├── lib/
│ └── utils.ts
└── ui/
└── toast.tsx
Generates the following items in public/r
directory.
public/
└── r/
├── registry.json
└── new-york/
├── toasty.json name: new-york-toasty target: blocks/new-york/toasty.tsx
├── toaster.json name: new-york-toaster target: components/new-york/toaster.tsx
├── use-toast.json name: new-york-use-toast target: hooks/new-york/use-toast.ts
├── utils.json name: new-york-utils target: lib/new-york/utils.ts
└── toast.json name: new-york-toast target: components/ui/new-york/toast.tsx
- Use direct name for default registry.
blocks/
└── toasty.tsx
components/
├── ui/
│ └── dialog.tsx
└── toaster.tsx
hooks/
└── use-toast.ts
lib/
└── utils.ts
Generates the following items in public/r
directory.
public/
└── r/
├── registry.json
├── toasty.json name: toasty target: blocks/toasty.tsx
├── component.json name: toaster target: components/toaster.tsx
├── use-toast.json name: use-toast target: hooks/use-toast.ts
├── utils.json name: utils target: lib/utils.ts
└── toast.json name: toast target: components/ui/toast.tsx
- Use
<registry-name>
sub-directory for named registry.
blocks/
└── new-york/
└── toasty.tsx
components/
├── new-york/
│ └── toaster.tsx
└── ui/
└── new-york/
└── toast.tsx
hooks/
└── new-york/
└── use-toast.ts
lib/
└── new-york/
└── utils.ts
Generates the following items in public/r
directory.
public/
└── r/
├── registry.json
└── new-york/
├── toasty.json name: new-york-toasty target: blocks/new-york/toasty.tsx
├── toaster.json name: new-york-toaster target: components/new-york/toaster.tsx
├── use-toast.json name: new-york-use-toast target: hooks/new-york/use-toast.ts
├── utils.json name: new-york-utils target: lib/new-york/utils.ts
└── toast.json name: new-york-toast target: components/ui/new-york/toast.tsx