The components.json file is an optional configuration file for the Untitled UI CLI. Use it to customize import aliases and paths for your project structure.
Overview
The components.json file allows you to configure how the CLI handles import paths and file locations when adding components to your project. This is particularly useful for:
- Monorepos with custom workspace aliases
- Projects with non-standard directory structures
- Teams that want consistent component installation paths
Note: The components.json file is optional. If you don't have one, the CLI will auto-detect your project structure from tsconfig.json and prompt you for paths as needed.
Creating components.json
Create a components.json file in the root of your project (or the folder where you run the CLI):
{ "aliases": { "components": "@/components/", "utils": "@/utils/", "hooks": "@/hooks/", "styles": "@/styles/" }, "examples": "app" }
Configuration options
aliases
The aliases object defines the import path prefixes used in your component files. These must match your tsconfig.json path mappings.
{ "aliases": { "components": "@/components/", "utils": "@/utils/", "hooks": "@/hooks/", "styles": "@/styles/" } }
| Property | Description |
|---|---|
components |
Import alias for component files (e.g., @/components/, @workspace/ui/components/) |
utils |
Import alias for utility functions (e.g., @/utils/, ~/lib/utils/) |
hooks |
Import alias for React hooks (e.g., @/hooks/) |
styles |
Import alias for style files (e.g., @/styles/) |
Important: Aliases must be valid tsconfig path aliases, not relative paths. The CLI uses your tsconfig.json to resolve these aliases to actual filesystem locations.
examples
The examples property specifies where example page files should be installed. This is useful when working in a monorepo where your web app is in a different directory.
{ "examples": "../../apps/web" }
How aliases work
When you add a component, the CLI performs two key operations using your aliases:
1. Import statement transformation
The CLI rewrites import statements in component code to match your aliases:
// Original component code import { Button } from "@/components/base/buttons/button"; import { cx } from "@/utils/cx"; Â // After transformation (if your alias is @workspace/ui/) import { Button } from "@workspace/ui/components/base/buttons/button"; import { cx } from "@workspace/ui/utils/cx";
2. File path resolution
The CLI uses your tsconfig.json paths to determine where to place files on disk:
// tsconfig.json { "compilerOptions": { "paths": { "@workspace/ui/*": ["./packages/ui/src/*"] } } }
With the above config, a component with path components/base/button.tsx would be installed to ./packages/ui/src/components/base/button.tsx.
Alias requirements
Critical: Aliases in components.json must be valid tsconfig path aliases. Relative paths like ../../components will not work correctly.
Why relative paths don't work
The CLI uses the tsconfig-paths library to resolve aliases to filesystem locations. This library only understands aliases defined in your tsconfig.json paths configuration.
| Alias Format | Works? | Reason |
|---|---|---|
@/components/ |
Yes | Resolved via tsconfig paths |
@workspace/ui/ |
Yes | Resolved via tsconfig paths |
~/components/ |
Yes | Resolved via tsconfig paths |
../../components/ |
No | Cannot be resolved by tsconfig-paths |
/absolute/path/ |
No | Cannot be resolved by tsconfig-paths |
Correct setup
To use custom aliases, you must configure both your tsconfig.json and components.json:
Configure tsconfig.json
Add your path mappings to tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@workspace/ui/*": ["./packages/ui/src/*"] } } }
Configure components.json
Reference the same aliases in components.json:
{ "aliases": { "components": "@workspace/ui/components/", "utils": "@workspace/ui/utils/", "hooks": "@workspace/ui/hooks/", "styles": "@workspace/ui/styles/" } }
Add components
Now the CLI will correctly resolve paths and transform imports:
npx untitledui@latest add button
Example configurations
Standard Next.js project
{ "aliases": { "components": "@/components/", "utils": "@/utils/", "hooks": "@/hooks/", "styles": "@/styles/" }, "framework": "next-app" }
With corresponding tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }
Monorepo with shared UI package
{ "aliases": { "components": "@workspace/ui/components/", "utils": "@workspace/ui/utils/", "hooks": "@workspace/ui/hooks/", "styles": "@workspace/ui/styles/" }, "examples": "../../apps/web" }
With corresponding tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@workspace/ui/*": ["./packages/ui/src/*"] } } }
Vite project with custom alias
{ "aliases": { "components": "~/components/", "utils": "~/lib/", "hooks": "~/hooks/", "styles": "~/styles/" }, "framework": "vite" }
With corresponding tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", "paths": { "~/*": ["./src/*"] } } }
FAQs
Please refer to our frequently asked questions page for more.
No, it's optional. The CLI will auto-detect your project structure from tsconfig.json and prompt you for any missing information.
Make sure your aliases match the path mappings in your tsconfig.json. The CLI uses tsconfig-paths to resolve aliases, so they must be valid tsconfig path aliases (like @/components/), not relative paths (like ../../components/).
No, relative paths like ../../components/ won't work. The CLI requires valid tsconfig path aliases that can be resolved through your tsconfig.json paths configuration.
Place it in the root of your project, or in the directory where you run the CLI. For monorepos, place it in the package directory where you want to install components.
No, the CLI only reads from components.json. It never modifies or creates this file automatically.
Set up path mappings in your tsconfig.json (e.g., @workspace/ui/*: [./packages/ui/src/*]), then reference those same aliases in your components.json. See the Monorepo integration guide for detailed instructions.
Aliases are the import prefixes used in your code (e.g., @/components/). Paths are the resolved filesystem locations where files are actually stored. The CLI automatically resolves aliases to paths using your tsconfig.json.
Yes, you can specify different aliases for components, utils, hooks, and styles. Each will be resolved independently based on your tsconfig.json paths.