components.json

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/"
    }
}
PropertyDescription
componentsImport alias for component files (e.g., @/components/, @workspace/ui/components/)
utilsImport alias for utility functions (e.g., @/utils/, ~/lib/utils/)
hooksImport alias for React hooks (e.g., @/hooks/)
stylesImport alias for style files (e.g., @/styles/)
appImport alias for @/app/ imports (e.g., @workspace/web/app/)
srcFallback alias for any other @/ import that none of the keys above cover (e.g., ~/)

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"
}

version

The version property pins the component library version the CLI pulls ("7" or "8"). It is optional and defaults to "8". The upgrade command sets it to "8" when a migration completes. See Version support.

{
    "version": "7"
}

The CLI reads only aliases, examples and version; any other keys are ignored.

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 FormatWorks?Reason
@/components/YesResolved via tsconfig paths
@workspace/ui/YesResolved via tsconfig paths
~/components/YesResolved via tsconfig paths
../../components/NoCannot be resolved by tsconfig-paths
/absolute/path/NoCannot 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/"
    }
}

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/"
    }
}

With corresponding tsconfig.json:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "~/*": ["./src/*"]
        }
    }
}

FAQs

Please refer to our frequently asked questions page for more.

No, it's optional. Without it, the CLI detects your project structure from tsconfig.json and prompts you for any missing information, such as where to add components.

Each alias must match a path mapping in your tsconfig.json. The CLI resolves aliases with tsconfig-paths, so it needs tsconfig path aliases like @/components/; relative paths like ../../components/ and absolute paths can't be resolved.

In the directory where you run the CLI, usually your project root. If you run add with --dir, the CLI looks for it in that directory instead. For monorepos, place it in the package directory where you want to install components.

Only the upgrade command does: after a run without --dry-run, it sets version to "8" in your existing components.json. It never creates the file, and no other command modifies it.

Put the Untitled UI settings (aliases, examples, version) in an untitledui.json file instead. The CLI recognizes a shadcn/ui components.json and doesn't take its aliases from it, and an untitledui.json always takes priority when present.

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 guide for detailed instructions.

Yes. Set components, utils, hooks and styles separately, plus app for @/app/ imports and src as a fallback for any other @/ import. Each one is resolved independently through your tsconfig.json paths.