How to Configure Component Aliases and Custom Output Paths for shadcn Components
Configure component aliases by editing the aliases object in components.json or via interactive prompts during shadcn init, and set custom output paths using the -o flag with shadcn registry:build or shadcn build.
The shadcn-ui/ui repository uses a centralized configuration system driven by components.json to manage how components are imported and where generated files are stored. This configuration file controls the scaffolding pipeline, allowing you to customize import aliases for different module categories and specify custom directories for registry build outputs.
Understanding the components.json Configuration File
The components.json file serves as the single source of truth for the shadcn CLI. Located at the root of your project (or package root in monorepos), it defines style preferences, TypeScript settings, Tailwind configuration, and critically, the alias map that the CLI uses to resolve imports.
Alias Configuration Structure
Aliases are defined under the aliases key as path mappings. According to the source code in packages/shadcn/src/utils/get-config.ts (lines 75-89), the configuration loader validates and resolves these aliases using TypeScript path-mapping resolution. The system supports five distinct alias categories:
components– Base path for UI componentsutils– Utility functions (typicallycnhelpers)lib– Shared library codehooks– Custom React hooksui– Specific UI component directory (often mirrorscomponents)
Configuring Import Aliases in shadcn
You can configure aliases either interactively during project initialization or by manually editing components.json after setup.
Interactive Setup During Initialization
When running npx shadcn@latest init, the CLI prompts for alias configuration. As implemented in packages/shadcn/src/commands/init.ts (lines 84-94), the interactive flow asks for:
- The import alias for components (e.g.,
@/components) - The import alias for utility functions (e.g.,
@/lib/utils)
These values are written directly to components.json under the aliases object.
Manual Configuration in components.json
For advanced setups, particularly in monorepos, manual configuration provides finer control. The template at templates/monorepo-next/packages/ui/components.json (lines 13-19) demonstrates a typical monorepo alias structure:
{
"aliases": {
"components": "@myorg/ui/src/components",
"utils": "@myorg/ui/src/lib/utils",
"hooks": "@myorg/ui/src/hooks",
"lib": "@myorg/ui/src/lib",
"ui": "@myorg/ui/src/components"
}
}
After editing components.json, subsequent shadcn add commands automatically resolve imports using the new alias mappings via the transform-import.ts transformer.
Setting Custom Output Paths for Registry Builds
When building a custom component registry, you can specify where the generated JSON artifacts are written using the --output (or -o) flag.
Using the --output Flag
Both the standard build command and the registry-specific build command support custom output directories. As defined in packages/shadcn/src/commands/registry/build.ts (lines 15-31) and mirrored in packages/shadcn/src/commands/build.ts (lines 15-31), the CLI accepts:
# Build registry to default ./public/r
shadcn registry:build
# Build registry to custom directory
shadcn registry:build -o ./dist/custom-registry
shadcn registry:build --output ./public/my-components
The same flag works for the experimental build command:
shadcn build -o ./output
How Output Directory Resolution Works
The CLI handles path resolution and directory creation automatically. In packages/shadcn/src/preflights/preflight-build.ts (lines 17-18), the preflight step resolves the provided path relative to the current working directory and ensures the directory exists:
// Conceptual flow from preflight-build.ts
const outputDir = path.resolve(cwd, options.output);
await fs.mkdir(outputDir, { recursive: true });
This ensures that custom output paths are created recursively if they don't exist, preventing errors during the file write operations that follow in the build logic.
Key Implementation Details from Source Code
The alias system relies on several key utilities in the shadcn codebase:
packages/shadcn/src/utils/get-config.ts(lines 75-89): Validates and loadscomponents.json, resolving alias paths using TypeScript's path mapping resolution.packages/shadcn/src/utils/transform-import.ts: Rewrites import statements in generated components to match the configured aliases fromcomponents.json.packages/shadcn/src/preflights/preflight-registry.ts(lines 18-42): Handles output directory validation and creation for registry builds, similar to the standard build preflight.
Summary
- Component aliases are configured in
components.jsonunder thealiaseskey, supportingcomponents,utils,lib,hooks, anduimappings. - Interactive configuration is available during
shadcn initvia prompts defined inpackages/shadcn/src/commands/init.ts. - Custom output paths for registry builds use the
-oor--outputflag withshadcn registry:buildorshadcn build. - The CLI automatically creates missing output directories via preflight checks in
preflight-build.tsandpreflight-registry.ts.
Frequently Asked Questions
What are the default alias keys supported by shadcn?
The components.json alias configuration supports five specific keys: components (base component directory), utils (utility functions like cn), lib (shared library code), hooks (custom React hooks), and ui (UI-specific components). These are validated and resolved by the configuration loader in packages/shadcn/src/utils/get-config.ts.
Can I change aliases after initializing a project?
Yes, you can modify aliases at any time by editing the aliases object in your components.json file. After making changes, subsequent shadcn add commands will automatically use the updated paths when generating imports, as the CLI re-reads the configuration on each execution via get-config.ts.
How do I configure aliases for a monorepo setup?
For monorepos, specify package-scoped aliases in your components.json using your workspace's import conventions. For example, set "components": "@myorg/ui/src/components" and "utils": "@myorg/ui/src/lib/utils" to map imports to your shared UI package. The template at templates/monorepo-next/packages/ui/components.json demonstrates this pattern for Next.js monorepos.
What happens if the custom output directory doesn't exist?
The CLI automatically creates the specified output directory if it doesn't exist. During the preflight phase of both shadcn build and shadcn registry:build, the code in packages/shadcn/src/preflights/preflight-build.ts (lines 17-18) executes fs.mkdir(outputDir, { recursive: true }), ensuring the full path is created recursively before any files are written.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →