Skip to content

feat(fullstack init --next): flatten nuxt-base-template into projects/app/ post-clone#86

Merged
pascal-klesse merged 2 commits intomainfrom
feat/flatten-nuxt-base-template-on-init
May 3, 2026
Merged

feat(fullstack init --next): flatten nuxt-base-template into projects/app/ post-clone#86
pascal-klesse merged 2 commits intomainfrom
feat/flatten-nuxt-base-template-on-init

Conversation

@pascal-klesse
Copy link
Copy Markdown
Member

Summary

lt fullstack init --next clones lenneTech/nuxt-base-starter (or
#next) into projects/app/, but the cloned repo is a wrapper —
the root package.json is the npm scaffolder create-nuxt-base,
and the actual Nuxt app lives at projects/app/nuxt-base-template/.
The generated monorepo's pnpm-workspace.yaml and the README's
cd projects/app && pnpm install && pnpm dev therefore point at the
wrapper, not the app, so install resolves the wrong dependencies and
pnpm dev has nothing to run.

This PR makes setupNuxt flatten the wrapper layout after a
successful clone: the contents of nuxt-base-template/ (including
dotfiles like .env.example, .gitignore, .npmrc) replace the
cloned root, and the wrapper-only files (index.js, pnpm-lock.yaml,
the scaffolder package.json, etc.) disappear. After the flatten,
projects/app/ IS the Nuxt app — exactly what the README and
workspace already assume.

Friction log

LLM-test 2026-05-03 #3 entry 20:30cd projects/app && pnpm install && pnpm dev fails because the cloned root is the
create-nuxt-base scaffolder. Workaround the friction-author
used: cd projects/app/nuxt-base-template && pnpm install --ignore-workspace && pnpm dev.

Before / After

Before                                  After
projects/app/                           projects/app/
├── package.json  (create-nuxt-base)    ├── package.json  (nuxt-base-template)
├── index.js                            ├── nuxt.config.ts
├── pnpm-lock.yaml                      ├── app/app.vue
├── README.md                           ├── .env.example
└── nuxt-base-template/                 └── …
    ├── package.json  (the real app)
    ├── nuxt.config.ts
    ├── app/app.vue
    └── …

Backward compatibility

  • Both branches affected, intentional. Both main and next of
    nuxt-base-starter ship the wrapper today, so the flatten benefits
    the legacy default-branch path too — not just --next. If a future
    branch drops the wrapper and ships the app at the root, the flatten
    becomes a no-op (no nuxt-base-template/ subdir = nothing to do).
  • Link mode untouched. --frontend-link is a symlink to the
    user's local checkout; flattening would tear out the source tree.
    The flatten only runs when templateHelper.setup returns
    method === 'clone'.
  • Defense-in-depth. The template is staged into a sibling tmp
    dir before dest is wiped. If staging fails (corrupt clone, future
    repo reshape, or nuxt-base-template exists as a stray file rather
    than a directory), the original layout stays untouched and the
    flatten returns { flattened: false, reason }. The pre-flatten
    layout is annoying but functional — better than wiping a user's
    clone over an unexpected layout.

Test plan

  • New unit suite __tests__/fullstack-init-next-flatten.test.ts
    covers the happy path (flatten happens, dotfiles survive,
    wrapper-only files are removed), the no-op path (already-flat
    layouts), the defensive abort (stray file at the subdir name),
    and a source-introspection guard so a future refactor can't
    silently drop the call site.
  • Full Jest suite green (npm test — 165 passed, 1 skipped).
  • Lint clean (npm run lint).
  • Manual smoke: lt fullstack init --next --name lt-flatten-test --noConfirm against the rebuilt CLI confirmed
    projects/app/package.json has name: nuxt-base-template,
    projects/app/nuxt-base-template/ is gone, dotfiles
    (.env.example, .gitignore, .npmrc, .nuxtrc) survived,
    and nuxt.config.ts + app/ are at the project root.

🤖 Generated with Claude Code

pascal-klesse and others added 2 commits May 3, 2026 21:25
…/app/ post-clone

`lenneTech/nuxt-base-starter` ships a wrapper repo: the root
`package.json` is the `create-nuxt-base` scaffolder (a separate npm
package), and the actual Nuxt app lives one level deeper under
`nuxt-base-template/`. After `lt fullstack init --next`, the generated
monorepo's `pnpm-workspace.yaml` and the README's
`cd projects/app && pnpm install && pnpm dev` pointed at the wrapper,
so install resolved the wrong dependencies and `pnpm dev` had nothing
to run (LLM-test 2026-05-03 friction #3 entry 20:30).

After cloning, `setupNuxt` now flattens the layout: the contents of
`nuxt-base-template/` (including dotfiles) replace the cloned root,
and the wrapper-only files (`index.js`, `pnpm-lock.yaml`, the
scaffolder `package.json`, etc.) disappear. The flatten only runs on
clone — link mode points at the user's local checkout and must not
have its template subdir torn out.

Defense-in-depth: stage the template into a sibling tmp dir before
wiping `dest`. If extraction fails (corrupt clone, future repo
reshape that drops the wrapper), the original layout stays untouched.
Both `main` and `next` branches of `nuxt-base-starter` ship the
wrapper today, so this fix also benefits the legacy default-branch
path, not just `--next`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e-declare `filesystem`

ts-jest treats every test file as part of one TypeScript program, so
my new file's top-level `const { filesystem } = require('gluegun')`
collided with the same declaration in
`fullstack-claude-md-patching.test.ts` (TS2451). The other
`fullstack-init-next-*.test.ts` files already document this gotcha
and require lazily inside the describe block — follow the same
pattern. Local Jest happened to pass (different ts-jest config
between local and CI), but CI failed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pascal-klesse pascal-klesse merged commit c35aeb9 into main May 3, 2026
1 check passed
@pascal-klesse pascal-klesse deleted the feat/flatten-nuxt-base-template-on-init branch May 3, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant