apps/v4/content/docs/registry/namespace.mdx
Namespaced registries let you configure multiple resource sources in one project. This means you can install components, libraries, utilities, AI prompts, configuration files, and other resources from various registries, whether they're public, third-party, or your own custom private libraries.
Registry namespaces are prefixed with @ and provide a way to organize and reference resources from different sources. Resources can be any type of content: components, libraries, utilities, hooks, AI prompts, configuration files, themes, and more. For example:
@shadcn/button - UI component from the shadcn registry@v0/dashboard - Dashboard component from the v0 registry@ai-elements/input - AI prompt input from an AI elements registry@acme/auth-utils - Authentication utilities from your company's private registry@ai/chatbot-rules - AI prompt rules from an AI resources registry@themes/dark-mode - Theme configuration from a themes registryWe intentionally designed the namespace system to be decentralized. There is a central open source registry index for open source namespaces but you are free to create and use any namespace you want.
This decentralized approach gives you complete flexibility to organize your resources however makes sense for your organization.
You can create multiple registries for different purposes:
{
"registries": {
"@acme-ui": "https://registry.acme.com/ui/{name}.json",
"@acme-docs": "https://registry.acme.com/docs/{name}.json",
"@acme-ai": "https://registry.acme.com/ai/{name}.json",
"@acme-themes": "https://registry.acme.com/themes/{name}.json",
"@acme-internal": {
"url": "https://internal.acme.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${INTERNAL_TOKEN}"
}
}
}
}
This allows you to:
{
"@components": "https://cdn.company.com/components/{name}.json",
"@hooks": "https://cdn.company.com/hooks/{name}.json",
"@utils": "https://cdn.company.com/utils/{name}.json",
"@prompts": "https://cdn.company.com/ai-prompts/{name}.json"
}
{
"@design": "https://create.company.com/registry/{name}.json",
"@engineering": "https://eng.company.com/registry/{name}.json",
"@marketing": "https://marketing.company.com/registry/{name}.json"
}
{
"@stable": "https://registry.company.com/stable/{name}.json",
"@latest": "https://registry.company.com/beta/{name}.json",
"@experimental": "https://registry.company.com/experimental/{name}.json"
}
Once configured, you can install resources using the namespace syntax:
npx shadcn@latest add @v0/dashboard
or multiple resources at once:
npx shadcn@latest add @acme/header @lib/auth-utils @ai/chatbot-rules
Add registries to your components.json:
{
"registries": {
"@v0": "https://v0.dev/chat/b/{name}",
"@acme": "https://registry.acme.com/resources/{name}.json"
}
}
Then start installing:
npx shadcn@latest add @acme/button
Registry names must follow these rules:
@ symbol@v0, @acme-ui, @my_companyThe pattern for referencing resources is: @namespace/resource-name
Namespaced registries are configured in your components.json file under the registries field.
The simplest way to configure a registry is with a URL template string:
{
"registries": {
"@v0": "https://v0.dev/chat/b/{name}",
"@acme": "https://registry.acme.com/resources/{name}.json",
"@lib": "https://lib.company.com/utilities/{name}",
"@ai": "https://ai-resources.com/r/{name}.json"
}
}
Note: The
{name}placeholder in the URL is automatically parsed and replaced with the resource name when you runnpx shadcn@latest add @namespace/resource-name. For example,@acme/buttonbecomeshttps://registry.acme.com/resources/button.json. See URL Pattern System for more details.
For registries that require authentication or additional parameters, use the object format:
{
"registries": {
"@private": {
"url": "https://api.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}",
"X-API-Key": "${API_KEY}"
},
"params": {
"version": "latest",
"format": "json"
}
}
}
}
Note: Environment variables in the format
${VAR_NAME}are automatically expanded from your environment (process.env). This works in URLs, headers, and params. For example,${REGISTRY_TOKEN}will be replaced with the value ofprocess.env.REGISTRY_TOKEN. See Authentication & Security for more details on using environment variables.
Registry URLs support the following placeholders:
{name} Placeholder (required)The {name} placeholder is replaced with the resource name:
{
"@acme": "https://registry.acme.com/{name}.json"
}
When installing @acme/button, the URL becomes: https://registry.acme.com/button.json
When installing @acme/auth-utils, the URL becomes: https://registry.acme.com/auth-utils.json
{style} Placeholder (optional)The {style} placeholder is replaced with the current style configuration:
{
"@themes": "https://registry.example.com/{style}/{name}.json"
}
With style set to new-york, installing @themes/card resolves to: https://registry.example.com/new-york/card.json
The style placeholder is optional. Use this when you want to serve different versions of the same resource. For example, you can serve a different version of a component for each style.
Use environment variables to securely store credentials:
{
"registries": {
"@private": {
"url": "https://api.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
Then set the environment variable:
REGISTRY_TOKEN=your_secret_token_here
{
"@github": {
"url": "https://api.github.com/repos/org/registry/contents/{name}.json",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
}
}
}
{
"@private": {
"url": "https://api.company.com/registry/{name}",
"headers": {
"X-API-Key": "${API_KEY}"
}
}
}
{
"@internal": {
"url": "https://registry.company.com/{name}.json",
"headers": {
"Authorization": "Basic ${BASE64_CREDENTIALS}"
}
}
}
{
"@secure": {
"url": "https://registry.example.com/{name}.json",
"params": {
"api_key": "${API_KEY}",
"client_id": "${CLIENT_ID}",
"signature": "${REQUEST_SIGNATURE}"
}
}
}
Some registries require multiple authentication methods:
{
"@enterprise": {
"url": "https://api.enterprise.com/v2/registry/{name}",
"headers": {
"Authorization": "Bearer ${ACCESS_TOKEN}",
"X-API-Key": "${API_KEY}",
"X-Workspace-Id": "${WORKSPACE_ID}"
},
"params": {
"version": "latest"
}
}
}
When working with namespaced registries, especially third-party or public ones, security is paramount. Here's how we handle security:
All resources fetched from registries are validated against our registry item schema before installation. This ensures:
registry:ui, registry:lib, etc.)Environment variables used for authentication are:
Example of secure configuration:
{
"registries": {
"@private": {
"url": "https://api.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${PRIVATE_REGISTRY_TOKEN}"
}
}
}
}
Never commit actual tokens to version control. Use .env.local:
PRIVATE_REGISTRY_TOKEN=actual_token_here
We strongly recommend using HTTPS for all registry URLs:
{
"registries": {
"@secure": "https://registry.example.com/{name}.json", // ✅ Good
"@insecure": "http://registry.example.com/{name}.json" // ❌ Avoid
}
}
Resources from registries are treated as data, not code:
The namespace system operates on a trust model:
components.jsonIf you're running your own registry:
Example secure registry setup:
{
"@company": {
"url": "https://registry.company.com/v1/{name}.json",
"headers": {
"Authorization": "Bearer ${COMPANY_TOKEN}",
"X-Registry-Version": "1.0"
}
}
}
The CLI provides transparency about what's being installed. You can see the payload of a registry item using the following command:
npx shadcn@latest view @acme/button
This will output the payload of the registry item to the console.
Resources can have dependencies across different registries:
{
"name": "dashboard",
"type": "registry:block",
"registryDependencies": [
"@shadcn/card", // From default registry
"@v0/chart", // From v0 registry
"@acme/data-table", // From acme registry
"@lib/data-fetcher", // Utility library
"@ai/analytics-prompt" // AI prompt resource
]
}
The CLI automatically resolves and installs all dependencies from their respective registries.
Understanding how dependencies are resolved internally is important if you're developing registries or need to customize third-party resources.
When you run npx shadcn@latest add @namespace/resource, the CLI does the following:
This means that if you run the following command:
npx shadcn@latest add @acme/auth @custom/login-form
The login-form.ts from @custom/login-form will override the login-form.ts from @acme/auth because it's resolved last.
You can leverage the dependency resolution process to override any third-party resource by adding them to your custom resource under registryDependencies and overriding with your own custom values.
Let's say you want to customize a button from a vendor registry:
1. Original vendor button (@vendor/button):
{
"name": "button",
"type": "registry:ui",
"files": [
{
"path": "components/ui/button.tsx",
"type": "registry:ui",
"content": "// Vendor's button implementation\nexport function Button() { ... }"
}
],
"cssVars": {
"light": {
"--button-bg": "blue"
}
}
}
2. Create your custom override (@my-company/custom-button):
{
"name": "custom-button",
"type": "registry:ui",
"registryDependencies": [
"@vendor/button" // Import original first
],
"cssVars": {
"light": {
"--button-bg": "purple" // Override the color
}
}
}
3. Install your custom version:
npx shadcn@latest add @my-company/custom-button
This installs the original button from @vendor/button and then overrides the cssVars with your own custom values.
Keep the original and add extensions:
{
"name": "extended-table",
"registryDependencies": ["@vendor/table"],
"files": [
{
"path": "components/ui/table-extended.tsx",
"content": "import { Table } from '@vendor/table'\n// Add your extensions\nexport function ExtendedTable() { ... }"
}
]
}
This will install the original table from @vendor/table and then add your extensions to components/ui/table-extended.tsx.
Override only specific files from a complex component:
{
"name": "custom-auth",
"registryDependencies": [
"@vendor/auth" // Has multiple files
],
"files": [
{
"path": "lib/auth-server.ts",
"type": "registry:lib",
"content": "// Your custom auth server"
}
]
}
When you install @custom/dashboard that depends on multiple resources:
{
"name": "dashboard",
"registryDependencies": [
"@shadcn/card", // 1. Resolved first
"@vendor/chart", // 2. Resolved second
"@custom/card" // 3. Resolved last (overrides @shadcn/card)
]
}
Resolution order:
@shadcn/card - installs to components/ui/card.tsx@vendor/chart - installs to components/ui/chart.tsx@custom/card - overwrites components/ui/card.tsx (if same target)You can implement versioning for your registry resources using query parameters. This allows users to pin specific versions or use different release channels.
{
"@versioned": {
"url": "https://registry.example.com/{name}",
"params": {
"version": "v2"
}
}
}
This resolves @versioned/button to: https://registry.example.com/button?version=v2
Use environment variables to control versions across your project:
{
"@stable": {
"url": "https://registry.company.com/{name}",
"params": {
"version": "${REGISTRY_VERSION}"
}
}
}
This allows you to:
REGISTRY_VERSION=v1.2.3 in productionImplement semantic versioning with range support:
{
"@npm-style": {
"url": "https://registry.example.com/{name}",
"params": {
"semver": "^2.0.0",
"prerelease": "${ALLOW_PRERELEASE}"
}
}
}
${VAR:-default} syntax/versions/{name})The shadcn CLI provides several commands for working with namespaced registries:
Install resources from any configured registry:
# Install from a specific registry
npx shadcn@latest add @v0/dashboard
# Install multiple resources
npx shadcn@latest add @acme/button @lib/utils @ai/prompt
# Install from URL directly
npx shadcn@latest add https://registry.example.com/button.json
# Install from local file
npx shadcn@latest add ./local-registry/button.json
Inspect registry items before installation:
# View a resource from a registry
npx shadcn@latest view @acme/button
# View multiple resources
npx shadcn@latest view @v0/dashboard @shadcn/card
# View from URL
npx shadcn@latest view https://registry.example.com/button.json
The view command displays:
Search for available resources in registries:
# Search a specific registry
npx shadcn@latest search @v0
# Search with query
npx shadcn@latest search @acme --query "auth"
# Search multiple registries
npx shadcn@latest search @v0 @acme @lib
# Limit results
npx shadcn@latest search @v0 --limit 10 --offset 20
# List all items (alias for search)
npx shadcn@latest list @acme
Search results include:
If you reference a registry that isn't configured:
npx shadcn@latest add @non-existent/component
Error:
Unknown registry "@non-existent". Make sure it is defined in components.json as follows:
{
"registries": {
"@non-existent": "[URL_TO_REGISTRY]"
}
}
If required environment variables are not set:
Registry "@private" requires the following environment variables:
• REGISTRY_TOKEN
Set the required environment variables to your .env or .env.local file.
404 Not Found:
The item at https://registry.company.com/button.json was not found. It may not exist at the registry.
This usually means:
401 Unauthorized:
You are not authorized to access the item at https://api.company.com/button.json
Check your authentication credentials and environment variables.
403 Forbidden:
Access forbidden for https://api.company.com/button.json
Verify your API key has the necessary permissions.
To make your registry compatible with the namespace system, you can serve any type of resource - components, libraries, utilities, AI prompts, themes, configurations, or any other shareable code/content:
Implement the registry item schema: Your registry must return JSON that conforms to the registry item schema.
Support the URL pattern: Include {name} in your URL template where the resource name will be inserted.
Define resource types: Use appropriate type fields to identify your resources (e.g., registry:ui, registry:lib, registry:ai, registry:theme, etc.).
Handle authentication (if needed): Accept authentication via headers or query parameters.
Document your namespace: Provide clear instructions for users to configure your registry:
{
"registries": {
"@your-registry": "https://your-domain.com/r/{name}.json"
}
}
The namespace parser uses the following regex pattern:
/^(@[a-zA-Z0-9](?:[a-zA-Z0-9-_]*[a-zA-Z0-9])?)\/(.+)$/
This ensures valid namespace formatting and proper component name extraction.
@namespace/component@namespaceWhen a component has dependencies from different registries, the resolver:
{name} placeholder is included in the URL@namespace/resource) to avoid ambiguity