Skip to content

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.

License

Notifications You must be signed in to change notification settings

nrjdalal/smart-registry

Repository files navigation

Smart Registry

Drop-in replacement for shadcn build, generate non-error prone registry with automatic detection of dependencies and files.

Twitter npm npm GitHub

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.

Demo Image

What is Zero-Configuration?

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.

Table of Contents

Usage

Automatic Detection

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.

Advanced Usage

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.

How it Works

Let's take the following directory structure to understand how Smart Registry works.

registry/
└── default/
    ├── lib/
    │   └── utils.ts
    └── ui/
        ├── button.tsx
        └── dialog.tsx
  1. Smart Registry will scan the registry directory and its sub-directories to find all the files (if no registry directory is found, it will scan the components or src/components directory).
  2. 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.
  3. It will then generate a registry.json file by combining all the <registry-item>.json files with all the properties required for shadcn add or open in v0.
public/
└── r/
    ├── button.json
    ├── dialog.json
    ├── registry.json
    └── utils.json

Extending Properties

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

With Zero-Configuration

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"
    }
  ]
}

Add Custom Properties

{
  "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"]
+  }
}

Additional Files to Include

{
  "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"
    }
  ]
}

External Registry Dependencies

{
  "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"]
}

Specify Dependency Version

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"
    }
  ]
}

Directory Structure

For registry Directory

  • 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

For registry Directory with Multiple Registries

  • 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

For components Directory

  • 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

For components Directory with Multiple Registries

  • 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

About

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.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published