- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
This guide will walk you through the process of setting up your own component registry. It assumes you already have a project with components and would like to turn it into a registry.
If you're starting a new registry project, you can use the registry template as a starting point. We have already configured it for you.
Requirements
You are free to design and host your custom registry as you see fit. The only requirement is that your registry items must be valid JSON files that conform to the registry-item schema specification.
If you'd like to see an example of a registry, we have a template project for you to use as a starting point.
registry.json
The registry.json is the entry point for the registry. It contains the registry's name, homepage, and defines all the items present in the registry.
Your registry must have this file (or JSON payload) present at the root of the registry endpoint. The registry endpoint is the URL where your registry is hosted.
The shadcn CLI will automatically generate this file for you when you run the build command.
Add a registry.json file
Create a registry.json file in the root of your project. Your project can be a Next.js, Vite, Vue, Svelte, PHP or any other framework as long as it supports serving JSON over HTTP.
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
// ...
]
}This registry.json file must conform to the registry schema specification.
Add a registry item
Create your component
Add your first component. Here's an example of a simple <HelloWorld /> component:
import { Button } from "@/components/ui/button"
export function HelloWorld() {
return <Button>Hello World</Button>
}Note: This example places the component in the registry/new-york
directory. You can place it anywhere in your project as long as you set the
correct path in the registry.json file and you follow the registry/[NAME]
directory structure.
registry
└── new-york
└── hello-world
└── hello-world.tsxAdd your component to the registry
To add your component to the registry, you need to add your component definition to registry.json.
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"items": [
{
"name": "hello-world",
"type": "registry:block",
"title": "Hello World",
"description": "A simple hello world component.",
"files": [
{
"path": "registry/new-york/hello-world/hello-world.tsx",
"type": "registry:component"
}
]
}
]
}You define your registry item by adding a name, type, title, description and files.
For every file you add, you must specify the path and type of the file. The path is the relative path to the file from the root of your project. The type is the type of the file.
You can read more about the registry item schema and file types in the registry item schema docs.
Build your registry
Install the shadcn CLI
pnpm add shadcn@latest
Add a build script
Add a registry:build script to your package.json file.
{
"scripts": {
"registry:build": "shadcn build"
}
}Run the build script
Run the build script to generate the registry JSON files.
pnpm registry:build
Note: By default, the build script will generate the registry JSON files
in public/r e.g public/r/hello-world.json.
You can change the output directory by passing the --output option. See the shadcn build command for more information.
Serve your registry
If you're running your registry on Next.js, you can now serve your registry by running the next server. The command might differ for other frameworks.
pnpm dev
Your files will now be served at http://localhost:3000/r/[NAME].json eg. http://localhost:3000/r/hello-world.json.
Content negotiation
The shadcn CLI supports HTTP Content Negotiation. This allows you to host your registry at any endpoint — including the root of your domain — and serve different content depending on who is asking.
From a single URL, you can serve:
- HTML to browsers — a landing page, documentation, or marketing site.
- JSON to the
shadcnCLI — an installable registry item. - Markdown to AI agents and LLMs — a machine-readable version of your content.
The client signals its preference using the Accept request header, and your server decides what to return.
Request headers
When the CLI makes a request to a registry, it sends the following headers:
- User-Agent:
shadcn - Accept:
application/vnd.shadcn.v1+json, application/json;q=0.9
Root hosting
By checking these headers on your server, you can route CLI traffic to an installable registry item while keeping browser traffic flowing to your documentation or homepage.
The examples below assume your built registry item is served at /r/index.json. Adjust the path to match your output.
In Next.js, express this as a rewrite in next.config.ts. This keeps the negotiation in the routing layer and avoids a Proxy function for this static rewrite:
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
async rewrites() {
return {
beforeFiles: [
{
source: "/",
has: [
{
type: "header",
key: "accept",
value: "(.*)application/vnd\\.shadcn\\.v1\\+json(.*)",
},
],
destination: "/r/index.json",
},
{
source: "/",
has: [
{
type: "header",
key: "user-agent",
value: "shadcn",
},
],
destination: "/r/index.json",
},
],
}
},
async headers() {
return [
{
source: "/",
headers: [{ key: "Vary", value: "Accept, User-Agent" }],
},
]
},
}
export default nextConfigOr, in an Express.js server:
app.get("/", (req, res) => {
res.vary("Accept")
res.vary("User-Agent")
// Check if the client prefers the shadcn vendor type.
if (req.accepts("application/vnd.shadcn.v1+json")) {
return res.json(registryData)
}
// Optional: Secondary check for the User-Agent.
if (req.get("User-Agent") === "shadcn") {
return res.json(registryData)
}
// Otherwise, serve your documentation or homepage.
res.send(htmlContent)
})This enables:
- Branded Registry URLs:
shadcn add https://ui.example.com - Shorter URLs: Users type your domain root, not
/r/or/registry/sub-paths. - Easy Mnemonics: Easier for users to remember and share your registry.
Publish your registry
To make your registry available to other developers, you can publish it by deploying your project to a public URL.
Guidelines
Here are some guidelines to follow when building components for a registry.
- Place your registry item in the
registry/[STYLE]/[NAME]directory. I'm usingnew-yorkas an example. It can be anything you want as long as it's nested under theregistrydirectory. - The following properties are required for the block definition:
name,description,typeandfiles. - It is recommended to add a proper name and description to your registry item. This helps LLMs understand the component and its purpose.
- Make sure to list all registry dependencies in
registryDependencies. A registry dependency is the name of the component in the registry eg.input,button,card, etc or a URL to a registry item eg.http://localhost:3000/r/editor.json. - Make sure to list all dependencies in
dependencies. A dependency is the name of the package in the registry eg.zod,sonner, etc. To set a version, you can use thename@versionformat eg.zod@^3.20.0. - Imports should always use the
@/registrypath. eg.import { HelloWorld } from "@/registry/new-york/hello-world/hello-world" - Ideally, place your files within a registry item in
components,hooks,libdirectories.
Install using the CLI
To install a registry item using the shadcn CLI, use the add command followed by the URL of the registry item.
pnpm dlx shadcn@latest add http://localhost:3000/r/hello-world.json
See the Namespaced Registries docs for more information on how to install registry items from a namespaced registry.
On This Page
Requirementsregistry.jsonAdd a registry.json fileAdd a registry itemCreate your componentAdd your component to the registryBuild your registryInstall the shadcn CLIAdd a build scriptRun the build scriptServe your registryContent negotiationRequest headersRoot hostingPublish your registryGuidelinesInstall using the CLI