Skip to content

[bug]: Import aliasing broken for custom registries in latest version of shadcn CLI #7849

@betich

Description

@betich

Describe the bug

In the latest version of the shadcn CLI (2.9.2), import aliasing (e.g. @/lib/utils) is not preserved correctly when using a registry JSON input. Instead, the output replaces the alias with a relative or root-based path (e.g. /lib/utils), which causes import resolution to fail in typical React/Next.js setups.

Example input:

Command run:

npx shadcn@latest https://<registry_url>/r/example.json

Registry file (example.json):

{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "example",
  "type": "registry:block",
  "title": "Example",
  "files": [
    {
      "path": "src/example.tsx",
      "content": "import { cn } from '@/lib/utils'\n\nexport default function Example() {\n  return (\n    <div className={cn('text-center text-lg font-semibold', 'text-gray-700')}>\n      Example Component\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/example.tsx"
    }
  ],
  "docs": "An Example component."
}

Expected output:

import { cn } from '@/lib/utils'

Actual output:

import { cn } from '/lib/utils' // ❌ alias removed

Notes:

  • I’ve tried many configurations, but the only reliable workaround is to:

    1. Downgrade to shadcn@2.8.0, where the aliasing works as expected. (shadcn@2.9.0 seems to be the breaking change)
    2. Set target: "" in the registry-item definition, which causes it to resolve to the default @/components/ui folder. In that context, the import aliasing works correctly.
    3. Set alias path to some other character other than @

Affected component/components

Custom Component Registry

How to reproduce

  1. Create a registry.json with the following content:
{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "shadcn",
  "homepage": "https://ui.shadcn.com",
  "items": [
    {
      "name": "example",
      "type": "registry:block",
      "title": "Example",
      "files": [
        {
          "path": "src/example.tsx",
          "type": "registry:component",
          "target": "components/example.tsx"
        }
      ],
      "docs": "An example component."
    }
  ]
}
  1. Create a component like src/example.tsx that uses @ import aliases
import { cn } from "@/lib/utils";

export default function Example() {
  return (
    <div className={cn("text-center text-lg font-semibold", "text-gray-700")}>
      Example Component
    </div>
  );
}
  1. Build the registry by running npx shadcn@latest build

  2. Serve the static json files. Then in another project, run the ShadCN CLI to create that component

npx shadcn@latest https://<registry_url>/r/example.json

  1. Observe the output in the generated component:

import { cn } from '/lib/utils'

Codesandbox/StackBlitz link

https://codesandbox.io/p/devbox/g47g23

Logs

System Info

shadcn: 2.9.2
Node.js: v22.14.0
pnpm: 9.15.0
npm: 10.9.2
System info: Darwin MacBooks-MacBook-Pro-2.local 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:48:46 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8103 arm64
Project Setup: React + Vite TS

Before submitting

  • I've made research efforts and searched the documentation
  • I've searched for existing issues

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions