- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- 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
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Questionnaire
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
このガイドでは、独自のレジストリを設定する手順を説明します。配布したいコンポーネント、フック、ユーティリティ、その他のファイルを含むプロジェクトがすでにあることを前提としています。
公開済みの GitHub リポジトリをお持ちの場合は、ルートに registry.json ファイルを追加するだけでレジストリにできます。 詳しくは GitHub レジストリ をご覧ください。
新しいレジストリプロジェクトを始める場合は、テンプレートプロジェクト を出発点として利用できます。すでに必要な設定が済んでいます。
要件#
カスタムレジストリは自由に設計・公開できます。唯一の要件は、レジストリカタログとレジストリ項目が registry スキーマ仕様 と registry-item スキーマ仕様 に準拠することです。
レジストリは、HTTP で JSON を配信できれば、Next.js、Vite、Vue、Svelte、PHP など、どのフレームワークでも構築できます。ルートに registry.json ファイルを置いた公開 GitHub リポジトリでも構いません。
レジストリの例を見たい場合は、出発点として利用できる テンプレートプロジェクト を用意しています。
registry.json#
registry.json はレジストリのエントリーポイントです。レジストリの名前やホームページを含み、レジストリに存在するすべての項目を定義します。
レジストリのエンドポイント(レジストリをホストしている URL)のルートに、このファイル(または JSON ペイロード)を配置する必要があります。
以下は registry.json ファイルの例です:
{
"$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"
}
]
}
]
}レジストリの構造#
ソースレジストリは、次の2通りの方法で構造化できます:
- ルートの単一
registry.jsonにすべての項目を定義する。 - ルートの
registry.jsonからincludeで複数のregistry.jsonファイルを組み合わせる。
方法A: 単一の registry.json#
プロジェクトのルートに registry.json ファイルを作成します。すべてのレジストリ項目を items 配列に追加します。これがレジストリを定義する最もシンプルな方法です。
{
"$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"
}
]
},
{
"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"
}
]
}
]
}この registry.json ファイルは registry スキーマ仕様 に準拠する必要があります。
方法B: include を使う#
大規模なレジストリでは、include を使って複数の registry.json ファイルからソースレジストリを構成できます。
registry.json
components
└── ui
├── button.tsx
├── input.tsx
└── registry.json
hooks
├── registry.json
├── use-media-query.ts
└── use-toggle.tsルートの registry.json では、レジストリのメタデータを定義し、ネストされたレジストリファイルを取り込みます。
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "acme",
"homepage": "https://acme.com",
"include": [
"components/ui/registry.json",
"hooks/registry.json"
]
}取り込まれる registry.json ファイルは、構成用の有効なレジストリファイルであり、name と homepage は省略できます。レジストリのメタデータを定義する必要があるのはルートの registry.json のみです。
{
"$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"
}
]
}
]
}{
"$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"
}
]
}
]
}include を使う場合、ファイルパスは項目を宣言している registry.json ファイルからの相対パスになります。
項目の追加#
UI コンポーネントの作成#
最初の項目を追加します。以下はシンプルな <Button /> コンポーネントの例です:
import * as React from "react"
export function Button(props: React.ComponentProps<"button">) {
return (
<button
{...props}
className="rounded-md bg-neutral-900 px-4 py-2 text-sm font-medium text-white"
/>
)
}注: この例ではコンポーネントを components/ui
ディレクトリに配置しています。registry.json
ファイルで正しいパスを設定すれば、プロジェクト内のどこに配置しても構いません。
components
└── ui
└── button.tsx項目をレジストリに追加する#
コンポーネントをレジストリに追加するには、registry.json に項目定義を追加します。include を使っている場合は、そのコンポーネントを所有する取り込み先の registry.json ファイルに項目を追加します。たとえば、UI コンポーネントは components/ui/registry.json に追加します。
{
"$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"
}
]
}
]
}レジストリ項目は、name、type、title、description、files を追加して定義します。
追加するファイルごとに、path と type を指定する必要があります。単一ファイル構成のレジストリでは、path はプロジェクトのルートからの相対パスです。include を使う場合は、path は項目を宣言している registry.json ファイルからの相対パスです。type はファイルの種類です。
レジストリ項目スキーマとファイルタイプについて詳しくは、registry-item スキーマのドキュメント をご覧ください。
レジストリの配信#
レジストリは、静的な JSON ファイルとしても、動的ルートハンドラーからも配信できます。
方法A: 静的な JSON ファイル#
ビルドコマンドを実行して、静的なレジストリ JSON ファイルを生成します。
pnpm dlx shadcn@latest build
ソースレジストリで include を使っている場合、shadcn build は取り込まれたレジストリを解決し、フラット化されたレジストリを出力ディレクトリに書き出します。生成された registry.json に include は含まれません。
注: 既定では、ビルドコマンドは public/r(例: public/r/button.json)にレジストリ JSON ファイルを生成します。--output オプションで出力ディレクトリを変更できます。詳しくは shadcn build コマンド をご覧ください。
Next.js でレジストリを実行している場合は、next サーバーを実行すればこれらのファイルを配信できます。他のフレームワークではコマンドが異なる場合があります。
pnpm dev
ファイルは http://localhost:3000/r/[NAME].json(例: http://localhost:3000/r/button.json)で配信されるようになります。
方法B: 動的ルートハンドラー#
リクエスト時にソースの registry.json からレジストリ JSON を配信したい場合は、shadcn/registry のプロデューサー側ローダー API を使います。
shadcn をランタイム依存関係としてインストールします:
pnpm add shadcn
loadRegistry を使ってレジストリカタログを配信します。
import { loadRegistry } from "shadcn/registry"
export async function GET() {
try {
const registry = await loadRegistry()
return Response.json(registry)
} catch (error) {
console.error(error)
return Response.json({ error: "Failed to load registry." }, { status: 500 })
}
}loadRegistryItem を使って個々のレジストリ項目を配信します。
import { loadRegistryItem, RegistryItemNotFoundError } from "shadcn/registry"
export async function GET(
_request: Request,
context: {
params: Promise<{
name: string
}>
}
) {
const { name } = await context.params
try {
const item = await loadRegistryItem(name)
return Response.json(item)
} catch (error) {
if (error instanceof RegistryItemNotFoundError) {
return Response.json(
{ error: `Registry item "${name}" was not found.` },
{ status: 404 }
)
}
console.error(error)
return Response.json(
{ error: "Failed to load registry item." },
{ status: 500 }
)
}
}どちらのローダーも JSON を返す前に include を解決するため、shadcn build を実行しなくても、ルートハンドラーで同じソースの registry.json 構造を使えます。
レジストリのテスト#
レジストリを配信できるようになったら、他の開発者が使うのと同じ CLI コマンドでテストします。
URL を使う場合#
list や search など項目を検出するコマンドにはカタログ URL を使います。view や add など特定の項目を読み取り・インストールするコマンドには項目 URL を使います。
項目の一覧表示#
まず、レジストリカタログが検出できることを確認します。
pnpm dlx shadcn@latest list http://localhost:3000/r/registry.json
項目の検索#
クエリでレジストリを検索します。
pnpm dlx shadcn@latest search http://localhost:3000/r/registry.json --query button
項目の表示#
次に、1つのレジストリ項目を名前で表示します。
pnpm dlx shadcn@latest view http://localhost:3000/r/button.json
項目の追加#
インストールフローをテストするには、項目をインストールしたいプロジェクトで add を実行します。
pnpm dlx shadcn@latest add http://localhost:3000/r/button.json
名前空間を使う場合#
レジストリの追加#
名前空間を使ってレジストリをテストすることもできます。components.json ファイルがあるプロジェクトで、プロジェクトにレジストリ URL テンプレートを追加します。
pnpm dlx shadcn@latest registry add @acme=http://localhost:3000/r/{name}.json
{name} プレースホルダーは項目 JSON ファイルに解決される必要があります。たとえば、@acme/button は http://localhost:3000/r/button.json に解決されます。カタログは引き続き http://localhost:3000/r/registry.json で個別に配信されます。
項目の一覧表示#
次に、レジストリ内の項目を一覧表示します。
pnpm dlx shadcn@latest list @acme
項目の検索#
クエリでレジストリを検索します。
pnpm dlx shadcn@latest search @acme --query button
項目の表示#
1つのレジストリ項目を名前で表示します。
pnpm dlx shadcn@latest view @acme/button
項目の追加#
インストールフローをテストするには、項目をインストールしたいプロジェクトで add を実行します。
pnpm dlx shadcn@latest add @acme/button
詳しくは 名前空間付きレジストリ のドキュメントをご覧ください。
レジストリの公開#
レジストリを他の開発者に利用可能にするには、プロジェクトを公開 URL にデプロイします。デプロイ後は、ユーザーは項目 URL から直接項目をインストールできますし、レジストリをプロジェクトの名前空間として追加することもできます。
名前空間の設定手順の共有#
@acme/button のような名前空間で項目をインストールしてほしい場合は、プロジェクトにレジストリ URL テンプレートを追加するようユーザーに案内します。{name} プレースホルダーは、CLI がレジストリ項目を解決する際に項目名に置き換えられます。
テンプレートは項目 JSON ファイルに解決される必要があります。たとえば、@acme/button は https://acme.com/r/button.json に解決されます。レジストリカタログは引き続き https://acme.com/r/registry.json で個別に配信してください。
CLI で名前空間を追加できます。
pnpm dlx shadcn@latest registry add @acme=https://acme.com/r/{name}.json
または、components.json ファイルの registries フィールドに手動で追加することもできます。
{
"registries": {
"@acme": "https://acme.com/r/{name}.json"
}
}ユーザーは名前空間を指定してレジストリの項目を利用できるようになります。
pnpm dlx shadcn@latest add @acme/button
名前空間をレジストリインデックスに追加する#
レジストリがオープンソースで公開されている場合は、名前空間を公式レジストリインデックスに申請できます。これにより、ユーザーは完全な URL テンプレートを貼り付ける代わりに、名前だけで名前空間を追加できるようになります。
申請要件について詳しくは レジストリインデックス のドキュメントをご覧ください。
ガイドライン#
レジストリ用にコンポーネントを構築する際のガイドラインは次のとおりです。
- レジストリ項目は
registry/[STYLE]/[NAME]ディレクトリに配置します。ここでは例としてdefaultを使っています。registryディレクトリ配下にネストされていれば、任意の名前で構いません。 - ブロックでは、次のプロパティが必須です:
name、description、type、files。 - レジストリ項目には適切な名前と説明を付けることを推奨します。LLM がコンポーネントとその目的を理解するのに役立ちます。
- すべてのレジストリ依存関係を
registryDependenciesに記載してください。レジストリ依存関係とは、button、@acme/input-form、acme/ui/button、http://localhost:3000/r/editor.jsonのような項目アドレスです。 - すべての依存関係を
dependenciesに記載してください。依存関係とは、レジストリ内のパッケージ名(例:zod、sonnerなど)です。バージョンを指定する場合はname@version形式(例:zod@^3.20.0)を使えます。 - インポートは常に
@/registryパスを使ってください。 例:import { HelloWorld } from "@/registry/default/hello-world/hello-world" - 理想的には、レジストリ項目内のファイルを
components、hooks、libディレクトリに配置します。