diff --git a/.changeset/rotten-humans-cover.md b/.changeset/rotten-humans-cover.md new file mode 100644 index 00000000000..893b2f5b07d --- /dev/null +++ b/.changeset/rotten-humans-cover.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +add include to registry.json diff --git a/apps/v4/content/docs/(root)/v0.mdx b/apps/v4/content/docs/(root)/_v0.mdx similarity index 100% rename from apps/v4/content/docs/(root)/v0.mdx rename to apps/v4/content/docs/(root)/_v0.mdx diff --git a/apps/v4/content/docs/(root)/meta.json b/apps/v4/content/docs/(root)/meta.json index a1ad4895976..ee767a33b39 100644 --- a/apps/v4/content/docs/(root)/meta.json +++ b/apps/v4/content/docs/(root)/meta.json @@ -11,7 +11,6 @@ "[CLI](/docs/cli)", "monorepo", "skills", - "v0", "javascript", "blocks", "figma", diff --git a/apps/v4/content/docs/changelog/2026-05-registry-include.mdx b/apps/v4/content/docs/changelog/2026-05-registry-include.mdx new file mode 100644 index 00000000000..31dea7b17f0 --- /dev/null +++ b/apps/v4/content/docs/changelog/2026-05-registry-include.mdx @@ -0,0 +1,98 @@ +--- +title: May 2026 - Registry Include +description: Organize large registries with included registry.json files. +date: 2026-05-20 +--- + +We've added support for `include` in `registry.json`. + +Registry authors can now organize a large source registry across multiple +`registry.json` files and compose them with `shadcn build`. + +```txt +registry.json +components +└── ui + ├── button.tsx + ├── input.tsx + └── registry.json +hooks +├── registry.json +├── use-media-query.ts +└── use-toggle.ts +``` + +{/* prettier-ignore */} +```json title="registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "name": "acme", + "homepage": "https://acme.com", + "include": [ + "components/ui/registry.json", + "hooks/registry.json" + ] +} +``` + +Included `registry.json` files are valid registry files for composition and may +omit `name` and `homepage`. Only the root `registry.json` must define the +registry metadata. + +```json title="components/ui/registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "items": [ + { + "name": "button", + "type": "registry:ui", + "files": [ + { + "path": "button.tsx", + "type": "registry:ui" + } + ] + } + ] +} +``` + +## Build output + +`shadcn build` resolves included registries and writes a flattened +`registry.json` without `include`. Item file paths are preserved from the root +registry, so a file declared in `components/ui/registry.json` is written as +`components/ui/button.tsx` in the built registry item. + +## Registry loaders + +The `shadcn/registry` package also exports `loadRegistry` and +`loadRegistryItem` for dynamic registry routes. + +```ts title="app/r/registry.json/route.ts" showLineNumbers +import { loadRegistry } from "shadcn/registry" + +export async function GET() { + const registry = await loadRegistry() + + return Response.json(registry) +} +``` + +```ts title="app/r/[name].json/route.ts" showLineNumbers +import { loadRegistryItem } from "shadcn/registry" + +export async function GET( + _: Request, + { params }: { params: Promise<{ name: string }> } +) { + const { name } = await params + const item = await loadRegistryItem(name) + + return Response.json(item) +} +``` + +See the [registry.json documentation](/docs/registry/registry-json#include) and +[getting started guide](/docs/registry/getting-started#structure-your-registry) +for more details. diff --git a/apps/v4/content/docs/registry/getting-started.mdx b/apps/v4/content/docs/registry/getting-started.mdx index 2b96384a819..02fa0455d70 100644 --- a/apps/v4/content/docs/registry/getting-started.mdx +++ b/apps/v4/content/docs/registry/getting-started.mdx @@ -9,7 +9,9 @@ If you're starting a new registry project, you can use the [registry template](h ## 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](/docs/registry/registry-item-json). +You are free to design and host your custom registry as you see fit. The only requirement is that your registry catalog and registry items must be valid JSON files that conform to the [registry schema specification](/docs/registry/registry-json) and [registry-item schema specification](/docs/registry/registry-item-json). + +Your registry can be a Next.js, Vite, Vue, Svelte, PHP or any other framework as long as it supports serving JSON over HTTP. If you'd like to see an example of a registry, we have a [template project](https://github.com/shadcn-ui/registry-template) for you to use as a starting point. @@ -19,11 +21,40 @@ The `registry.json` is the entry point for the registry. It contains the registr 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. +Here's an example `registry.json` file: + +```json title="registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "name": "acme", + "homepage": "https://acme.com", + "items": [ + { + "name": "button", + "type": "registry:ui", + "title": "Button", + "description": "A simple button component.", + "files": [ + { + "path": "components/ui/button.tsx", + "type": "registry:ui" + } + ] + } + ] +} +``` + +## Structure your registry + +You can structure your source registry in one of two ways: + +- Define all items in a single root `registry.json`. +- Use a root `registry.json` with `include` to compose multiple `registry.json` files. -## Add a registry.json file +### Option A: Single registry.json -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. +Create a `registry.json` file in the root of your project. Add all your registry items to the `items` array. This is the simplest way to define a registry. ```json title="registry.json" showLineNumbers { @@ -31,44 +62,171 @@ Create a `registry.json` file in the root of your project. Your project can be a "name": "acme", "homepage": "https://acme.com", "items": [ - // ... + { + "name": "button", + "type": "registry:ui", + "title": "Button", + "description": "A simple button component.", + "files": [ + { + "path": "components/ui/button.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "hello-world", + "type": "registry:block", + "title": "Hello World", + "description": "A simple hello world component.", + "registryDependencies": ["button"], + "files": [ + { + "path": "registry/default/hello-world/hello-world.tsx", + "type": "registry:component" + } + ] + } ] } ``` This `registry.json` file must conform to the [registry schema specification](/docs/registry/registry-json). -## Add a registry item +### Option B: Using include -### Create your component +For larger registries, you can use `include` to compose your source registry +from multiple `registry.json` files. -Add your first component. Here's an example of a simple `` component: +```txt +registry.json +components +└── ui + ├── button.tsx + ├── input.tsx + └── registry.json +hooks +├── registry.json +├── use-media-query.ts +└── use-toggle.ts +``` -```tsx title="registry/new-york/hello-world/hello-world.tsx" showLineNumbers -import { Button } from "@/components/ui/button" +The root `registry.json` defines the registry metadata and includes the nested +registry files. -export function HelloWorld() { - return +{/* prettier-ignore */} +```json title="registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "name": "acme", + "homepage": "https://acme.com", + "include": [ + "components/ui/registry.json", + "hooks/registry.json" + ] +} +``` + +Included `registry.json` files are valid registry files for composition and may +omit `name` and `homepage`. Only the root `registry.json` must define the +registry metadata. + +```json title="components/ui/registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "items": [ + { + "name": "button", + "type": "registry:ui", + "files": [ + { + "path": "button.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "input", + "type": "registry:ui", + "files": [ + { + "path": "input.tsx", + "type": "registry:ui" + } + ] + } + ] +} +``` + +```json title="hooks/registry.json" showLineNumbers +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "items": [ + { + "name": "use-toggle", + "type": "registry:hook", + "files": [ + { + "path": "use-toggle.ts", + "type": "registry:hook" + } + ] + }, + { + "name": "use-media-query", + "type": "registry:hook", + "files": [ + { + "path": "use-media-query.ts", + "type": "registry:hook" + } + ] + } + ] +} +``` + +When using `include`, file paths are relative to the `registry.json` file that +declares the item. + +## Add an item + +### Create a UI component + +Add your first item. Here's an example of a simple `