#1933·shadcn-vue

[Bug]: Registry file `target` ignores the project source directory (Nuxt `app/`, Vite `src/`) — upstream's `isSrcDir` handling is commented out

Author: andyjamesnCreated Aug 11, 2026Updated Aug 11, 2026

Describe the bug

When a registry item file declares an explicit target, the CLI joins it directly onto the project root, ignoring the project's source directory. In packages/cli/src/utils/updaters/update-files.ts (~L338–364), the upstream React CLI's isSrcDir branch is present but commented out:

typescript
// return options.isSrcDir
//   ? path.join(config.resolvedPaths.cwd, 'src', target.replace('src/', ''))
//   : path.join(config.resolvedPaths.cwd, target.replace('src/', ''))

return assertPathWithin(
  path.join(config.resolvedPaths.cwd, target.replace('src/', '')),
  config.resolvedPaths.cwd,
  file,
)

For comparison, shadcn-ui/uipackages/shadcn/src/utils/updaters/update-files.ts resolves the same case with options.isSrcDir ? path.join(cwd, "src", ...) : ... (plus alias-aware targets via resolveAliasTarget), so React registries with targets work on both src/ and root layouts.

This affects any non-root layout: Nuxt 4 (app/), and standard Vite + Vue projects (src/ — the surviving target.replace('src/', '') strips the prefix but never re-adds it, so src/-layout consumers also receive root-level files). Only root-layout projects resolve targets correctly today.

Real-world impact

Registry authors are already working around this by shipping per-framework JSON variants with the layout hardcoded into targets — e.g. one public Vue registry ships "target": "~/app/components/ui/clipboard/Clipboard.vue" (Nuxt-only; the same file breaks a Vite + Vue consumer by creating a root app/ folder), while its React variant ships ~/components/ui/.... With srcDir-aware resolution, one registry output would serve all layouts, as it does for React.

The alias-based default mapping (no target) resolves correctly through components.json, so component-type items have a workaround — but target is the only mechanism for files outside the aliased directories (pages, config files, assets), which is exactly where this bites.

Reproduction

  1. npx nuxi init test-app && cd test-app — Nuxt 4 (srcDir app/), then npx shadcn-vue@latest init
  2. Host a minimal registry item whose file has "type": "registry:file", "target": "components/ui/foo/Foo.vue"
  3. npx shadcn-vue@latest add <url-to-item.json>
  4. File is created at <root>/components/ui/foo/Foo.vue; expected app/components/ui/foo/Foo.vue

Suggested fix

Hardcoding a prefix (src/ or app/) can't be fully correct in the Vue ecosystem — Nuxt alone has two layouts (main app app/…, layers <layer>/… without app/), plus custom srcDirs. A more robust approach may be resolving non-~/ targets against the project's configured paths (as declared in components.json aliases) — effectively porting upstream's resolveAliasTarget alongside or instead of the isSrcDir branch — keeping ~/ as the explicit root-anchor escape hatch. Happy to open a PR if either direction sounds right to the maintainers.