[Bug]: Registry file `target` ignores the project source directory (Nuxt `app/`, Vite `src/`) — upstream's `isSrcDir` handling is commented out
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:
// 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/ui → packages/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
npx nuxi init test-app && cd test-app— Nuxt 4 (srcDirapp/), thennpx shadcn-vue@latest init- Host a minimal registry item whose file has
"type": "registry:file","target": "components/ui/foo/Foo.vue" npx shadcn-vue@latest add <url-to-item.json>- File is created at
<root>/components/ui/foo/Foo.vue; expectedapp/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.
Source: unovue/shadcn-vue