- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- React Hook Form
- Hover Card
- Input
- Input OTP
- Label
- Menubar
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll-area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
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.
Table of Contents
- Overview
- Decentralized Namespace System
- Getting Started
- Registry Naming Convention
- Configuration
- Authentication & Security
- Versioning
- Dependency Resolution
- Built-in Registries
- CLI Commands
- Error Handling
- Creating Your Own Registry
- Example Configurations
- Technical Details
- Best Practices
- Troubleshooting
Overview
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 registry
Decentralized Namespace System
We intentionally designed the namespace system to be decentralized. There is no central registrar for namespaces. 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:
- Organize by type: Separate UI components, documentation, AI resources, etc.
- Organize by team: Different teams can maintain their own registries
- Organize by visibility: Public vs. private resources
- Organize by version: Stable vs. experimental registries
- No naming conflicts: Since there's no central authority, you don't need to worry about namespace collisions
Examples of Multi-Registry Setups
By Resource Type
{
"@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"
}
By Team or Department
{
"@design": "https://design.company.com/registry/{name}.json",
"@engineering": "https://eng.company.com/registry/{name}.json",
"@marketing": "https://marketing.company.com/registry/{name}.json"
}
By Stability
{
"@stable": "https://registry.company.com/stable/{name}.json",
"@latest": "https://registry.company.com/beta/{name}.json",
"@experimental": "https://registry.company.com/experimental/{name}.json"
}
Getting Started
Installing Resources
Once configured, you can install resources using the namespace syntax:
pnpm dlx shadcn@latest add @v0/dashboard
or multiple resources at once:
pnpm dlx shadcn@latest add @acme/header @lib/auth-utils @ai/chatbot-rules
Quick Configuration
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:
pnpm dlx shadcn@latest add @acme/button
Registry Naming Convention
Registry names must follow these rules:
- Start with
@
symbol - Contain only alphanumeric characters, hyphens, and underscores
- Examples of valid names:
@v0
,@acme-ui
,@my_company
The pattern for referencing resources is: @namespace/resource-name
Configuration
Namespaced registries are configured in your components.json
file under the registries
field.
Basic Configuration
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/button
becomeshttps://registry.acme.com/resources/button.json
. See URL Pattern System for more details.
Advanced Configuration
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.
URL Pattern System
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.
Authentication & Security
Environment Variables
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
Authentication Methods
Bearer Token (OAuth 2.0)
{
"@github": {
"url": "https://api.github.com/repos/org/registry/contents/{name}.json",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
}
}
}
API Key in Headers
{
"@private": {
"url": "https://api.company.com/registry/{name}",
"headers": {
"X-API-Key": "${API_KEY}"
}
}
}
Basic Authentication
{
"@internal": {
"url": "https://registry.company.com/{name}.json",
"headers": {
"Authorization": "Basic ${BASE64_CREDENTIALS}"
}
}
}
Query Parameter Authentication
{
"@secure": {
"url": "https://registry.example.com/{name}.json",
"params": {
"api_key": "${API_KEY}",
"client_id": "${CLIENT_ID}",
"signature": "${REQUEST_SIGNATURE}"
}
}
}
Multiple Authentication Methods
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"
}
}
}
Security Considerations
When working with namespaced registries, especially third-party or public ones, security is paramount. Here's how we handle security:
Resource Validation
All resources fetched from registries are validated against our registry item schema before installation. This ensures:
- Structure validation: Resources must conform to the expected JSON schema
- Type safety: Resource types are validated (
registry:ui
,registry:lib
, etc.) - No arbitrary code execution: Resources are data files, not executable scripts
Environment Variable Security
Environment variables used for authentication are:
- Never logged: The CLI never logs or displays environment variable values
- Expanded at runtime: Variables are only expanded when needed, not stored
- Isolated per registry: Each registry maintains its own authentication context
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
HTTPS Enforcement
We strongly recommend using HTTPS for all registry URLs:
- Encrypted transport: Prevents man-in-the-middle attacks
- Certificate validation: Ensures you're connecting to the legitimate registry
- Credential protection: Headers and tokens are encrypted in transit
{
"registries": {
"@secure": "https://registry.example.com/{name}.json", // ✅ Good
"@insecure": "http://registry.example.com/{name}.json" // ❌ Avoid
}
}
Content Security
Resources from registries are treated as data, not code:
- JSON parsing only: Resources must be valid JSON
- Schema validation: Must match the registry item schema
- File path restrictions: Files can only be written to configured paths
- No script execution: The CLI doesn't execute any code from registry resources
Registry Trust Model
The namespace system operates on a trust model:
- You trust what you install: Only add registries you trust to your configuration
- Explicit configuration: Registries must be explicitly configured in
components.json
- No automatic registry discovery: The CLI never automatically adds registries
- Dependency transparency: All dependencies are clearly listed in registry items
Best Practices for Registry Operators
If you're running your own registry:
- Use HTTPS always: Never serve registry content over HTTP
- Implement authentication: Require API keys or tokens for private registries
- Rate limiting: Protect your registry from abuse
- Content validation: Validate resources before serving them
Example secure registry setup:
{
"@company": {
"url": "https://registry.company.com/v1/{name}.json",
"headers": {
"Authorization": "Bearer ${COMPANY_TOKEN}",
"X-Registry-Version": "1.0"
}
}
}
Inspecting Resources Before Installation
The CLI provides transparency about what's being installed. You can see the payload of a registry item using the following command:
pnpm dlx shadcn@latest view @acme/button
This will output the payload of the registry item to the console.
Dependency Resolution
Basic Dependency Resolution
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.
Advanced Dependency Resolution
Understanding how dependencies are resolved internally is important if you're developing registries or need to customize third-party resources.
How Resolution Works
When you run npx shadcn@latest add @namespace/resource
, the CLI does the following:
- Clears registry context to start fresh
- Fetches the main resource from the specified registry
- Recursively resolves dependencies from their respective registries
- Applies topological sorting to ensure proper installation order
- Deduplicates files based on target paths (last one wins)
- Deep merges configurations (tailwind, cssVars, css, envVars)
This means that if you run the following command:
pnpm dlx 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.
Overriding Third-Party Resources
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.
Example: Customizing a Third-Party Button
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:
pnpm dlx 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.
Advanced Override Patterns
Extending Without Replacing
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
.
Partial Override (Multi-file Resources)
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"
}
]
}
Resolution Order Example
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 tocomponents/ui/card.tsx
@vendor/chart
- installs tocomponents/ui/chart.tsx
@custom/card
- overwritescomponents/ui/card.tsx
(if same target)
Key Resolution Features
- Source Tracking: Each resource knows which registry it came from, avoiding naming conflicts
- Circular Dependency Prevention: Automatically detects and prevents circular dependencies
- Smart Installation Order: Dependencies are installed first, then the resources that use them
We intentionally designed the namespace system to be decentralized. There is no central registrar for namespaces. 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:
- Organize by type: Separate UI components, documentation, AI resources, etc.
- Organize by team: Different teams can maintain their own registries
- Organize by visibility: Public vs. private resources
- Organize by version: Stable vs. experimental registries
- No naming conflicts: Since there's no central authority, you don't need to worry about namespace collisions
Examples of Multi-Registry Setups
By Resource Type
{
"@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"
}
By Team or Department
{
"@design": "https://design.company.com/registry/{name}.json",
"@engineering": "https://eng.company.com/registry/{name}.json",
"@marketing": "https://marketing.company.com/registry/{name}.json"
}
By Stability
{
"@stable": "https://registry.company.com/stable/{name}.json",
"@latest": "https://registry.company.com/beta/{name}.json",
"@experimental": "https://registry.company.com/experimental/{name}.json"
}
Built-in Registries
The @shadcn
namespace is built-in and always available:
pnpm dlx shadcn@latest add @shadcn/button
This is equivalent to installing from the default shadcn/ui registry.
Versioning
You can implement versioning for your registry resources using query parameters. This allows users to pin specific versions or use different release channels.
Basic Version Parameter
{
"@versioned": {
"url": "https://registry.example.com/{name}",
"params": {
"version": "v2"
}
}
}
This resolves @versioned/button
to: https://registry.example.com/button?version=v2
Dynamic Version Selection
Use environment variables to control versions across your project:
{
"@stable": {
"url": "https://registry.company.com/{name}",
"params": {
"version": "${REGISTRY_VERSION}"
}
}
}
This allows you to:
- Set
REGISTRY_VERSION=v1.2.3
in production - Override per environment (dev, staging, prod)
Semantic Versioning
Implement semantic versioning with range support:
{
"@npm-style": {
"url": "https://registry.example.com/{name}",
"params": {
"semver": "^2.0.0",
"prerelease": "${ALLOW_PRERELEASE}"
}
}
}
Version Resolution Best Practices
- Use environment variables for version control across environments
- Provide sensible defaults using the
${VAR:-default}
syntax - Document version schemes clearly for registry users
- Support version pinning for reproducible builds
- Implement version discovery endpoints (e.g.,
/versions/{name}
) - Cache versioned resources appropriately with proper cache headers
CLI Commands
The shadcn CLI provides several commands for working with namespaced registries:
Adding Resources
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
Viewing Resources
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:
- Resource metadata (name, type, description)
- Dependencies and registry dependencies
- File contents that will be installed
- CSS variables and Tailwind configuration
- Required environment variables
Searching Registries
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:
- Resource name and type
- Description
- Registry source
Error Handling
Registry Not Configured
If you reference a registry that isn't configured:
pnpm dlx 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]"
}
}
Missing Environment Variables
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.
Resource Not Found
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:
- The resource name is misspelled
- The resource doesn't exist in the registry
- The registry URL pattern is incorrect
Authentication Failures
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.
Creating Your Own Registry
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"
}
}
Technical Details
Parser Pattern
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.
Resolution Process
- Parse: Extract namespace and component name from
@namespace/component
- Lookup: Find registry configuration for
@namespace
- Build URL: Replace placeholders with actual values
- Set Headers: Apply authentication headers if configured
- Fetch: Retrieve component from the resolved URL
- Validate: Ensure response matches registry item schema
- Resolve Dependencies: Recursively fetch any registry dependencies
Cross-Registry Dependencies
When a component has dependencies from different registries, the resolver:
- Maintains separate authentication contexts for each registry
- Resolves each dependency from its respective source
- Deduplicates files based on target paths
- Merges configurations (tailwind, cssVars, etc.) from all sources
Best Practices
- Use environment variables for sensitive data like API keys and tokens
- Namespace your registry with a unique, descriptive name
- Document authentication requirements clearly for users
- Implement proper error responses with helpful messages
- Cache registry responses when possible to improve performance
- Support style variants if your components have multiple themes
Troubleshooting
Resources not found
- Verify the registry URL is correct and accessible
- Check that the
{name}
placeholder is included in the URL - Ensure the resource exists in the registry
- Confirm the resource type matches what the registry provides
Authentication issues
- Confirm environment variables are set correctly
- Verify API keys/tokens are valid and not expired
- Check that headers are being sent in the correct format
Dependency conflicts
- Review resources with the same name from different registries
- Use fully qualified names (
@namespace/resource
) to avoid ambiguity - Check for circular dependencies between registries
- Ensure resource types are compatible when mixing registries
On This Page
Table of ContentsOverviewDecentralized Namespace SystemExamples of Multi-Registry SetupsBy Resource TypeBy Team or DepartmentBy StabilityGetting StartedInstalling ResourcesQuick ConfigurationRegistry Naming ConventionConfigurationBasic ConfigurationAdvanced ConfigurationURL Pattern System{name}
Placeholder (required){style}
Placeholder (optional)Authentication & SecurityEnvironment VariablesAuthentication MethodsBearer Token (OAuth 2.0)API Key in HeadersBasic AuthenticationQuery Parameter AuthenticationMultiple Authentication MethodsSecurity ConsiderationsResource ValidationEnvironment Variable SecurityHTTPS EnforcementContent SecurityRegistry Trust ModelBest Practices for Registry OperatorsInspecting Resources Before InstallationDependency ResolutionBasic Dependency ResolutionAdvanced Dependency ResolutionHow Resolution WorksOverriding Third-Party ResourcesExample: Customizing a Third-Party ButtonAdvanced Override PatternsExtending Without ReplacingPartial Override (Multi-file Resources)Resolution Order ExampleKey Resolution FeaturesExamples of Multi-Registry SetupsBy Resource TypeBy Team or DepartmentBy StabilityBuilt-in RegistriesVersioningBasic Version ParameterDynamic Version SelectionSemantic VersioningVersion Resolution Best PracticesCLI CommandsAdding ResourcesViewing ResourcesSearching RegistriesError HandlingRegistry Not ConfiguredMissing Environment VariablesResource Not FoundAuthentication FailuresCreating Your Own RegistryTechnical DetailsParser PatternResolution ProcessCross-Registry DependenciesBest PracticesTroubleshootingResources not foundAuthentication issuesDependency conflicts