Skip to content

[bug]: Shadcn CLI incorrectly resolves workspace aliases and creates components in wrong location in monorepo setup #9239

@salvatorecontino

Description

@salvatorecontino

Describe the bug

Describe the bug

The Shadcn CLI fails to correctly resolve workspace aliases (e.g., @typewrite/ui) when installing components in a monorepo structure. Instead of creating components in the correct shared package location (packages/ui/src/components/), the CLI creates them in an incorrect nested path (apps/web/@typewrite/ui/components/).

Additionally, the CLI's path validation in resolvedPaths rejects relative paths that exit the current workspace (e.g., ../../packages/ui/...), causing validation errors even when the paths are correct for a monorepo structure.

Expected behavior

When running shadcn add <component> from apps/web in a monorepo:

  1. The CLI should correctly resolve the workspace alias @typewrite/ui to packages/ui
  2. Components should be installed in packages/ui/src/components/
  3. Dependencies should be installed in packages/ui/package.json
  4. The CLI should accept relative paths in resolvedPaths that reference other workspaces

Actual behavior

  1. The CLI creates components in apps/web/@typewrite/ui/components/ instead of packages/ui/src/components/
  2. The CLI treats @typewrite/ui as a literal path instead of resolving it to the workspace package
  3. Path validation fails when using relative paths like ../../packages/ui/... in resolvedPaths
  4. Dependencies are correctly installed in packages/ui/package.json (this part works)

Affected component/components

CLI command, path resolution, path validation & component installation

How to reproduce

Prerequisites

  1. A monorepo setup with Turborepo (or similar)
  2. Two workspaces:
    • apps/web (Next.js app)
    • packages/ui (shared UI package)

Steps to reproduce

  1. Setup monorepo structure:

    typewrite/
    ├── apps/
    │   └── web/
    │       └── components.json
    └── packages/
        └── ui/
            └── components.json
    
  2. Configure apps/web/components.json:

    {
      "$schema": "https://ui.shadcn.com/schema.json",
      "style": "default",
      "rsc": true,
      "tsx": true,
      "tailwind": {
        "config": "",
        "css": "../../packages/ui/src/styles/globals.css",
        "baseColor": "slate",
        "cssVariables": true,
        "prefix": ""
      },
      "iconLibrary": "lucide",
      "aliases": {
        "components": "@/components",
        "hooks": "@/hooks",
        "lib": "@/lib",
        "utils": "../../packages/ui/src/lib/utils",
        "ui": "../../packages/ui/src/components"
      },
      "resolvedPaths": {
        "components": "src/components",
        "hooks": "src/hooks",
        "lib": "src/lib",
        "utils": "../../packages/ui/src/lib/utils",
        "ui": "../../packages/ui/src/components"
      }
    }
  3. Configure packages/ui/components.json:

    {
      "$schema": "https://ui.shadcn.com/schema.json",
      "style": "default",
      "rsc": true,
      "tsx": true,
      "tailwind": {
        "config": "",
        "css": "src/styles/globals.css",
        "baseColor": "slate",
        "cssVariables": true,
        "prefix": ""
      },
      "iconLibrary": "lucide",
      "aliases": {
        "components": "@typewrite/ui/components",
        "utils": "@typewrite/ui/lib/utils",
        "hooks": "@typewrite/ui/hooks",
        "lib": "@typewrite/ui/lib",
        "ui": "@typewrite/ui/components"
      },
      "resolvedPaths": {
        "components": "src/components",
        "utils": "src/lib/utils",
        "hooks": "src/hooks",
        "lib": "src/lib",
        "ui": "src/components"
      }
    }
  4. Run the CLI command:

    cd apps/web
    pnpm dlx shadcn@latest add button --yes
  5. Observe the incorrect behavior:

    • Check if component is created in apps/web/@typewrite/ui/components/button.tsx (❌ wrong)
    • Expected location: packages/ui/src/components/button.tsx (✅ correct)

Alternative reproduction with workspace alias

If using workspace aliases in aliases field:

{
  "aliases": {
    "ui": "@typewrite/ui/components"
  }
}

The CLI will create files in apps/web/@typewrite/ui/components/ instead of resolving @typewrite/ui to the actual workspace package location.


Codesandbox/StackBlitz link

No response

Logs

### Example CLI output (when it works partially)


✓ Checking for updates...
✓ Resolved registry dependencies
✓ Installing dependencies...
  Installing @radix-ui/react-slot...
  Installing class-variance-authority...
  Installing clsx...
  Installing tailwind-merge...
✓ Dependencies installed successfully
✓ Component installed successfully


**Note**: The CLI reports success, but the component is installed in the wrong location.

### Error logs (when path validation fails)

If using relative paths in `resolvedPaths` that exit the workspace:


✗ Error: Invalid path in resolvedPaths: ../../packages/ui/src/components
  Path must be within the current workspace


### File structure after incorrect installation


apps/web/
├── @typewrite/          ← Incorrectly created directory
│   └── ui/
│       └── components/
│           └── button.tsx
└── components.json

packages/ui/
├── package.json         ← Dependencies correctly added here
└── src/
    └── components/      ← Component should be here, but isn't

System Info

### Environment

- **OS**: Windows 10 (Build 26200)
- **Node Version**: v22.14.0
- **Package Manager**: pnpm 8.15.1
- **Shadcn CLI Version**: `shadcn@latest` (latest as of 31/12/2025)

### Monorepo Setup

- **Monorepo Tool**: Turborepo 2.7.2
- **Workspace Manager**: pnpm workspaces
- **Project Structure**: 
  - Apps: `apps/web` (Next.js)
  - Packages: `packages/ui` (shared UI components)

### Package.json workspace configuration


{
  "workspaces": [
    "apps/*",
    "packages/*"
  ]
}


### TypeScript Configuration

- **TypeScript Version**: 5.9.3
- **Path Aliases**: Configured for `@typewrite/ui``packages/ui`

### Additional Context

- The issue occurs specifically when:
  1. Using workspace aliases (e.g., `@typewrite/ui`) in `aliases` field
  2. Using relative paths (e.g., `../../packages/ui/...`) in `resolvedPaths` field
  3. Running CLI from the app workspace (`apps/web`) instead of the UI package workspace

- **Workaround currently in use**: 
  - Custom PowerShell scripts to manually move components after CLI installation
  - Temporary modification of `components.json` to bypass validation

---

Before submitting

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

Metadata

Metadata

Assignees

No one assigned

    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