feat(vue): add @modular-vue/nuxt Nuxt 3 integration (PR-52) - #85
Conversation
Add a Nuxt 3 integration for the @modular-vue family. Nuxt owns the Vue
app and the vue-router instance, so this is the router-owning path over
@modular-vue/runtime (registry.resolve()): it grafts every module's
createRoutes() subtree onto Nuxt's router via router.addRoute() and
installs the modular contexts on the Nuxt Vue app.
Two seams:
- installModularApp(nuxtApp, registry, options?) — the runtime core.
Structural NuxtAppLike ({ vueApp, $router }) so the path takes no
nuxt/@nuxt/schema runtime dependency and stays unit-testable against a
real Vue app + vue-router. Forwards parentRouteName / authGuard /
providers / slotFilter / onModuleExit to resolve().
- A defineNuxtModule default export (configKey "modularVue") — the
zero-config path. Points modularVue.registry at a registry (or
factory) export and injects a runtime plugin (addPluginTemplate) that
calls installModularApp and exposes the manifest as $modular. The pure
plugin-source builder is unit-tested standalone.
Ships packages/vue-nuxt (@modular-vue/nuxt 0.1.0, experimental) with the
repo's standard build/test skeleton, 19 tests, a framework-mode-nuxt.md
guide, README package/guides/status entries, the shell-patterns see-also
link, and ci.yml / publish.yml plumbing. Resolves D6 and closes PR-52 in
the Vue support tracker.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nc4TqY91FV1GGJAncBYX6
|
Warning Review limit reached
Next review available in: 36 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughAdds the experimental ChangesNuxt package foundation
Release wiring
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Nuxt
participant ModularNuxtModule
participant installModularApp
participant Registry
participant VueRouter
Nuxt->>ModularNuxtModule: load modularVue configuration
ModularNuxtModule->>installModularApp: invoke generated plugin
installModularApp->>Registry: resolve with Nuxt router
Registry->>VueRouter: add module routes
installModularApp-->>Nuxt: provide modular manifest
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/vue-nuxt/src/install.ts (2)
108-115: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a runtime check for
$routerpresence.In Nuxt 3, the
$routerproperty is only injected if thepages/directory exists or if Vue Router is explicitly configured. If a user installs this module without configuring Nuxt for routing,nuxtApp.$routerwill beundefined, causingregistry.resolveto throw a cryptic error when it attempts to calladdRoute.Adding a fail-fast check improves the developer experience.
🛡️ Proposed fix to validate router
+ if (!nuxtApp.$router) { + throw new Error( + "installModularApp requires a Nuxt app with vue-router (e.g., a pages/ directory must exist)." + ); + } + const manifest = registry.resolve({ router: nuxtApp.$router, parentRouteName: options?.parentRouteName,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/vue-nuxt/src/install.ts` around lines 108 - 115, In the install flow before calling registry.resolve, validate that nuxtApp.$router exists and fail fast with a clear configuration error when it is absent. Preserve the existing resolve options and behavior when the router is available.
108-115: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a runtime fail-fast check for
$router.In Nuxt 3, the
$routerproperty is only injected if thepages/directory exists or if Vue Router is explicitly configured. If a user installs this module without configuring Nuxt for routing,nuxtApp.$routerwill beundefined, causingregistry.resolveto throw a cryptic error when it attempts to invokeaddRoute.Adding an explicit runtime check helps developers quickly identify the misconfiguration.
🛡️ Proposed fix to validate router presence
+ if (!nuxtApp.$router) { + throw new Error( + "installModularApp requires a Nuxt app with vue-router (e.g., a pages/ directory must exist)." + ); + } + const manifest = registry.resolve({ router: nuxtApp.$router, parentRouteName: options?.parentRouteName,🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/vue-nuxt/src/install.ts` around lines 108 - 115, Before calling registry.resolve in the install flow, validate that nuxtApp.$router is present and fail fast with a clear configuration error when it is undefined. Keep passing the existing router value to registry.resolve for configured applications, and leave the remaining resolve options unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/vue-nuxt/src/install.ts`:
- Around line 108-115: In the install flow before calling registry.resolve,
validate that nuxtApp.$router exists and fail fast with a clear configuration
error when it is absent. Preserve the existing resolve options and behavior when
the router is available.
- Around line 108-115: Before calling registry.resolve in the install flow,
validate that nuxtApp.$router is present and fail fast with a clear
configuration error when it is undefined. Keep passing the existing router value
to registry.resolve for configured applications, and leave the remaining resolve
options unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6f7645f8-7b88-4827-bae7-65b2d2dec193
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (18)
.github/workflows/ci.yml.github/workflows/publish.ymlREADME.mddocs/framework-mode-nuxt.mddocs/shell-patterns-vue-router.mddocs/vue-support-tracker.mdpackages/vue-nuxt/README.mdpackages/vue-nuxt/package.jsonpackages/vue-nuxt/src/index.test.tspackages/vue-nuxt/src/index.tspackages/vue-nuxt/src/install.test-d.tspackages/vue-nuxt/src/install.test.tspackages/vue-nuxt/src/install.tspackages/vue-nuxt/src/module.test.tspackages/vue-nuxt/src/module.tspackages/vue-nuxt/tsconfig.jsonpackages/vue-nuxt/vite.config.tspackages/vue-nuxt/vitest.config.ts
…registry path Address review findings on the @modular-vue/nuxt integration: - Add a runtime-only `./runtime` export (built from `src/install.ts`) and point the injected Nuxt plugin — and the own-plugin docs/JSDoc examples — at `@modular-vue/nuxt/runtime` instead of the package barrel. The barrel re-exports the `defineNuxtModule` default, which eagerly imports `@nuxt/kit` (a build-time toolkit); importing the installer from it dragged `@nuxt/kit` into the app's client/SSR runtime bundle. The runtime bundle is now @nuxt/kit-free. - Fix the module's default `registry` option from `~/modular.registry` to `~/modular/registry`, matching the documented convention everywhere else. Tests and typecheck updated accordingly; vite emits dist/index.js (barrel) and dist/runtime.js (installer only). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDNhgjLDRjem9pyJsuoeDU
…etup Raise docstring coverage over the pre-merge threshold: document the `install.test.ts` helpers (`newRegistry`, `page`, `routedModule`, `nuxtAppFor`) as JSDoc and add a docstring to the Nuxt module's `setup` hook. Comments only — no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SDNhgjLDRjem9pyJsuoeDU
|
Pushed follow-ups addressing the review and CI: Review findings
CI
Note: CodeRabbit's review was rate-limited and posted no line findings this run, so there were no review threads to resolve. Generated by Claude Code |
What & why
Adds Nuxt 3 support for the
@modular-vuefamily — the last remaining item in the Vue support initiative (docs/vue-support-tracker.mdPR-52, and it resolves D6).Nuxt owns the Vue app and the vue-router instance, so this is the router-owning path over
@modular-vue/runtime(registry.resolve()), not framework mode: it grafts every module'screateRoutes()subtree onto Nuxt's router viarouter.addRoute()and installs the modular contexts (shared deps, navigation, slots, modules) on the Nuxt Vue app.New package
packages/vue-nuxt→@modular-vue/nuxt0.1.0(experimental), with two seams:installModularApp(nuxtApp, registry, options?)— the runtime core. Takes the structuralNuxtAppLike({ vueApp, $router }, which a realNuxtAppsatisfies), so the path needs nonuxt/@nuxt/schemaruntime dependency and stays unit-testable against a live Vue app + vue-router. Callsregistry.resolve({ router: nuxtApp.$router, ...options }), installs the manifest onnuxtApp.vueApp, and returns it. ForwardsparentRouteName/authGuard/providers/slotFilter/onModuleExit.defineNuxtModuledefault export (configKey: "modularVue") — the zero-config path. PointmodularVue.registryat a registry (or per-request factory) export; the module transpiles the package and injects a runtime plugin (addPluginTemplate) that callsinstallModularAppand exposes the manifest as$modular. The pure plugin-source builder (buildModularPluginContents) is unit-tested standalone.Design notes:
resolve()notresolveManifest(): Nuxt creates the router, so there's no hostcreateRouter({ routes })to feedresolveManifest().routesinto;resolve()'s runtimeaddRoute()is the exact fit. Under SSR the registry is built per request (fresh app + router per request;resolve()is single-use) — documented, and covered by a test asserting the single-use throw on a reused singleton.addRouteserves client navigation immediately; a deep-linkable module subtree needs a Nuxt page to graft under (parentRouteName+ a shell/catch-all page). Documented in the guide.@nuxt/kitand@nuxt/schemaare external for both the JS bundle and the dts pass (theNuxtModule<ModuleOptions>annotation references@nuxt/schema).Also lands:
docs/framework-mode-nuxt.md, README package/guides/status entries, the Vue shell-patterns see-also link, the tracker update (PR-52 → done, D6 → resolved), andci.yml/publish.ymlplumbing for the new package. No example app or CI example-shell entry ships here (a Nuxt example would pull the full Nuxt toolchain into the examples workspace + CI matrix); the installer's real behavior is covered by the package suite.How it was verified
pnpm lintpasses — 147 typecheck tasks (incl.@modular-vue/nuxt#typecheck),oxfmt --checkclean,oxlintreports only pre-existing warnings in other packages (none invue-nuxt).pnpm test— 19 new tests pass:install.test.ts(8; route grafting, context injection,parentRouteNamenesting, auth guard, provider/onModuleExitforwarding, static slots, single-use throw),module.test.ts(8; plugin-source emission incl. factory-unwrap + JSON-escaping, module meta/defaults,setuptranspile +addPluginTemplate),index.test.ts(2; barrel),install.test-d.ts(2).vite buildproduces a cleandist(JS + dts);@nuxt/kit/@nuxt/schemastay unbundled. Full-workspacepnpm buildpasses.Checklist
pnpm lintpasses (typecheck + oxfmt + oxlint).pnpm test).@modular-vue/*package); it touches no@modular-frontend/*package and adds no React-binding capability, so no cross-family follow-up is needed.🤖 Generated with Claude Code
https://claude.ai/code/session_012nc4TqY91FV1GGJAncBYX6
Generated by Claude Code
Summary by CodeRabbit
@modular-vue/nuxt.