Skip to content

feat(v4)!: always use Vite DevTools, remove floating panel#952

Merged
antfu merged 7 commits intomainfrom
antfu/use-vite-devtools-kit
Mar 18, 2026
Merged

feat(v4)!: always use Vite DevTools, remove floating panel#952
antfu merged 7 commits intomainfrom
antfu/use-vite-devtools-kit

Conversation

@antfu
Copy link
Member

@antfu antfu commented Mar 17, 2026

Summary

  • Remove the viteDevTools module option — Nuxt DevTools now always integrates with Vite DevTools as a dock entry
  • Remove the built-in floating panel (draggable web component overlay) in favor of Vite DevTools' panel
  • Remove Picture-in-Picture popup feature and related globals
  • Rewire client.devtools.open/close/toggle and Shift+Alt+D shortcut to control Vite DevTools panel
  • Remove showPanel and minimizePanelInactive UI settings
  • Use getDevToolsClientContext() from @vitejs/devtools-kit v0.1.3 for clean panel control
  • Update migration guide documenting all breaking changes

Test plan

  • Run playground and verify Nuxt DevTools appears as a dock entry in Vite DevTools
  • Verify Shift+Alt+D opens Vite DevTools and switches to Nuxt DevTools entry
  • Verify component inspector still works
  • Verify client.devtools.open/close/toggle methods work correctly

🤖 Generated with Claude Code

- Remove viteDevTools option and always integrate with Vite DevTools as dock entry
- Remove built-in floating panel (NuxtDevtoolsFrame web components)
- Rewire client.devtools methods to control Vite DevTools panel
- Shift+Alt+D shortcut now toggles Nuxt DevTools entry in Vite DevTools
- Make @vitejs/devtools a direct dependency
- Remove showPanel and minimizePanelInactive UI settings
- Update migration guide with breaking changes

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 17, 2026

Deploying nuxt-devtools with  Cloudflare Pages  Cloudflare Pages

Latest commit: f17aea8
Status:🚫  Build failed.

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e5508bfe-6220-4036-8141-04e2a866afad

📥 Commits

Reviewing files that changed from the base of the PR and between c7f3ab6 and f17aea8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/devtools/package.json
  • packages/devtools/src/server-rpc/npm.ts
  • pnpm-workspace.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/devtools/package.json

📝 Walkthrough

Walkthrough

This PR removes the floating Picture-in-Picture devtools UI and related webcomponents (NuxtDevtoolsFrame, NuxtDevtoolsFrameBox, PictureInPictureButton), their styles, and frame-related state (popupWindow, popup API, NUXT_DEVTOOLS_IS_POPUP). It removes UI settings (showPanel, minimizePanelInactive) and related wiring, refactors client-side devtools to use the Vite DevTools context, and makes Vite DevTools integration always enabled (viteDevTools option removed). Several types and RPCs related to wizards/popups were removed, package dependency entries and workspace catalog versions updated, and a .context .gitignore rule was added.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(v4)!: always use Vite DevTools, remove floating panel' accurately describes the main changes: always integrating Vite DevTools and removing the floating panel component.
Description check ✅ Passed The description provides a clear summary of changes including removal of viteDevTools option, floating panel removal, Picture-in-Picture removal, API rewiring, and migration guide updates, all of which align with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch antfu/use-vite-devtools-kit
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can approve the review once all CodeRabbit's comments are resolved.

Enable the reviews.request_changes_workflow setting to automatically approve the review once all CodeRabbit's comments are resolved.

…obals

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
.gitignore (1)

63-63: Clarify the purpose of .context ignore pattern.

The addition of .context is not explained and doesn't appear directly related to the PR's stated objectives (Vite DevTools integration). Consider adding a brief comment above this entry to document what creates this directory and why it should be ignored.

📝 Example with documentation
+# AI coding assistant context (e.g., Cursor IDE)
 .context
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore at line 63, Add a short explanatory comment above the .context
entry in .gitignore describing what creates the .context directory (e.g., a
specific tool, editor, or build step) and why it should be ignored (temporary
files, secrets, or non-source artifacts), so reviewers understand its purpose;
update the .gitignore entry for ".context" and include the creator/tool name and
rationale in the comment (referencing the ".context" pattern in the file).
packages/devtools/src/module-main.ts (2)

65-65: Type safety: ctx is typed as any.

The ctx parameter uses any due to the early version of @vitejs/devtools (v0.1.x). Consider adding a TODO comment to revisit type definitions when the library stabilizes its public API.

💡 Suggested documentation
       devtools: {
-        setup(ctx: any) {
+        // TODO: Replace `any` with proper types when `@vitejs/devtools` exposes stable API types
+        setup(ctx: any) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/module-main.ts` at line 65, The parameter ctx in the
setup(ctx: any) function is currently typed as any; add a TODO comment
immediately above the setup method indicating this is a temporary any due to the
early `@vitejs/devtools` (v0.1.x) public API and that the type should be replaced
with the appropriate context type once the library stabilizes (i.e., revisit and
update the typing for setup(ctx) when `@vitejs/devtools` exposes a proper type).

69-69: Consider bundling the icon locally or using a data URI.

The icon URL points to an external resource (https://nuxt.com/assets/design-kit/icon-green.svg). If the developer is offline or the URL becomes unavailable, the dock entry may display without an icon. A local asset or base64-encoded data URI would improve reliability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/module-main.ts` at line 69, Replace the external icon
URL used in the dock entry (the icon property in the object in module-main.ts)
with a bundled local asset or a base64/data URI: import or require the SVG from
the package assets (e.g., an icons folder) and assign that imported module to
the icon property, or convert the SVG to a data URI string and set icon to that
string so the dock entry does not depend on https://nuxt.com; ensure the asset
is included in the package build so the path resolves at runtime.
packages/devtools/src/runtime/plugins/view/client.ts (1)

69-90: DevTools methods silently no-op when context is unavailable.

The toggle(), close(), open(), and navigate() methods silently do nothing if getViteDevToolsContext() returns null. This could confuse users if the Vite DevTools element hasn't mounted yet or if the internal API changed.

Consider logging a warning in development when context is unavailable.

💡 Suggested improvement
       toggle() {
         const ctx = getViteDevToolsContext()
         if (ctx)
           ctx.docks.toggleEntry('nuxt:devtools')
+        else if (import.meta.dev)
+          console.warn('[nuxt-devtools] Vite DevTools context not available')
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/runtime/plugins/view/client.ts` around lines 69 - 90,
The devtools methods toggle(), close(), open(), and navigate() silently no-op
when getViteDevToolsContext() returns null; update each method (toggle, close,
open, navigate) to detect a missing ctx and in non-production emit a clear
console.warn (or project logger) that includes the method name and that the Vite
DevTools context is unavailable (optionally include any available hint/info),
then bail out; ensure the warning is only emitted in development (check NODE_ENV
or the repo's isDev helper) so production behavior is unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/devtools/package.json`:
- Line 53: Remove the redundant devDependencies entry for "@vitejs/devtools"
from package.json so the package is only declared once (in dependencies); search
for the devDependencies block that contains "@vitejs/devtools" and delete that
line, then run your package manager (install/lockfile update) to sync changes —
ensure runtime imports in src/module-main.ts and
src/runtime/plugins/vite-devtools.client.ts continue to resolve from the single
dependencies entry.

In `@packages/devtools/src/runtime/plugins/view/client.ts`:
- Around line 23-34: The getViteDevToolsContext() routine currently reaches into
Vue internals (el._instance.props.context) and later uses undocumented fields
like ctx.docks and ctx.panel.store.value; make this explicit and defensive by
adding a clear comment above getViteDevToolsContext() stating it relies on
unsupported internals and may break, then wrap the extraction in a try-catch
that safely handles missing properties (return null) instead of throwing, and
where ctx.docks or ctx.panel.store.value are used elsewhere, add guards
(optional chaining / null checks) and graceful fallbacks or logs so the code
fails safely when the `@vitejs/devtools` internals change.

---

Nitpick comments:
In @.gitignore:
- Line 63: Add a short explanatory comment above the .context entry in
.gitignore describing what creates the .context directory (e.g., a specific
tool, editor, or build step) and why it should be ignored (temporary files,
secrets, or non-source artifacts), so reviewers understand its purpose; update
the .gitignore entry for ".context" and include the creator/tool name and
rationale in the comment (referencing the ".context" pattern in the file).

In `@packages/devtools/src/module-main.ts`:
- Line 65: The parameter ctx in the setup(ctx: any) function is currently typed
as any; add a TODO comment immediately above the setup method indicating this is
a temporary any due to the early `@vitejs/devtools` (v0.1.x) public API and that
the type should be replaced with the appropriate context type once the library
stabilizes (i.e., revisit and update the typing for setup(ctx) when
`@vitejs/devtools` exposes a proper type).
- Line 69: Replace the external icon URL used in the dock entry (the icon
property in the object in module-main.ts) with a bundled local asset or a
base64/data URI: import or require the SVG from the package assets (e.g., an
icons folder) and assign that imported module to the icon property, or convert
the SVG to a data URI string and set icon to that string so the dock entry does
not depend on https://nuxt.com; ensure the asset is included in the package
build so the path resolves at runtime.

In `@packages/devtools/src/runtime/plugins/view/client.ts`:
- Around line 69-90: The devtools methods toggle(), close(), open(), and
navigate() silently no-op when getViteDevToolsContext() returns null; update
each method (toggle, close, open, navigate) to detect a missing ctx and in
non-production emit a clear console.warn (or project logger) that includes the
method name and that the Vite DevTools context is unavailable (optionally
include any available hint/info), then bail out; ensure the warning is only
emitted in development (check NODE_ENV or the repo's isDev helper) so production
behavior is unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 952709fd-ba79-49de-a684-3e078d9d3641

📥 Commits

Reviewing files that changed from the base of the PR and between f82457d and fa7e755.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • .gitignore
  • docs/content/2.module/3.migration-v4.md
  • packages/devtools-kit/src/_types/options.ts
  • packages/devtools/client/pages/index.vue
  • packages/devtools/client/pages/settings.vue
  • packages/devtools/package.json
  • packages/devtools/src/constant.ts
  • packages/devtools/src/module-main.ts
  • packages/devtools/src/runtime/plugins/devtools.client.ts
  • packages/devtools/src/runtime/plugins/view/client.ts
  • packages/devtools/src/runtime/plugins/view/state.ts
  • packages/devtools/src/webcomponents/.generated/css.ts
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrame.ts
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrame.vue
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrameBox.vue
  • packages/devtools/src/webcomponents/index.ts
  • packages/devtools/src/webcomponents/style.css
💤 Files with no reviewable changes (10)
  • packages/devtools-kit/src/_types/options.ts
  • packages/devtools/src/webcomponents/index.ts
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrame.ts
  • packages/devtools/src/runtime/plugins/view/state.ts
  • packages/devtools/src/constant.ts
  • packages/devtools/src/webcomponents/style.css
  • packages/devtools/client/pages/index.vue
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrame.vue
  • packages/devtools/client/pages/settings.vue
  • packages/devtools/src/webcomponents/components/NuxtDevtoolsFrameBox.vue

"dependencies": {
"@nuxt/devtools-kit": "workspace:*",
"@nuxt/kit": "catalog:prod",
"@vitejs/devtools": "catalog:buildtools",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the duplicate dependency entries
cat packages/devtools/package.json | jq '{dependencies: .dependencies["@vitejs/devtools"], devDependencies: .devDependencies["@vitejs/devtools"]}'

Repository: nuxt/devtools

Length of output: 142


🏁 Script executed:

# Read the package.json to see context around the duplicate entries
head -n 110 packages/devtools/package.json | tail -n 60

Repository: nuxt/devtools

Length of output: 2379


🏁 Script executed:

# Search for actual usage of `@vitejs/devtools` in the codebase
rg "@vitejs/devtools" --type json --type ts --type js -i

Repository: nuxt/devtools

Length of output: 586


Remove @vitejs/devtools from devDependencies.

The package is already listed in dependencies (line 53) and is imported at runtime in src/module-main.ts and src/runtime/plugins/vite-devtools.client.ts. The devDependencies entry at line 102 is redundant and should be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/package.json` at line 53, Remove the redundant
devDependencies entry for "@vitejs/devtools" from package.json so the package is
only declared once (in dependencies); search for the devDependencies block that
contains "@vitejs/devtools" and delete that line, then run your package manager
(install/lockfile update) to sync changes — ensure runtime imports in
src/module-main.ts and src/runtime/plugins/vite-devtools.client.ts continue to
resolve from the single dependencies entry.

@arashsheyda
Copy link
Member

looks awesome! 1 question: the vite devtools has unocss, and then nuxt devtools also have it. is there a plan to remove it from nuxt devtools?

@arashsheyda
Copy link
Member

@antfu also I think nuxt devtools is breaking on pip mode
Screenshot 2026-03-17 at 12 36 55 AM

@antfu
Copy link
Member Author

antfu commented Mar 17, 2026

looks awesome! 1 question: the vite devtools has unocss, and then nuxt devtools also have it. is there a plan to remove it from nuxt devtools?

For non-nuxt-specific integrations, they should go into Vite DevTools and remove the registration from Nuxt in the future.

antfu and others added 2 commits March 18, 2026 11:05
Replace hacky DOM element instance access with the official
getDevToolsClientContext() API from @vitejs/devtools-kit v0.1.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/devtools/package.json (1)

53-54: ⚠️ Potential issue | 🟡 Minor

Remove duplicated @vitejs/devtools declaration.

@vitejs/devtools is now required in dependencies (Line 53), but it is still also listed in devDependencies (Line 103). Keep a single source of truth in dependencies.

Proposed fix
   "devDependencies": {
@@
-    "@vitejs/devtools": "catalog:buildtools",
#!/bin/bash
set -euo pipefail

jq -r '
  "dependencies:`@vitejs/devtools`=" + (.dependencies["@vitejs/devtools"] // "MISSING"),
  "devDependencies:`@vitejs/devtools`=" + (.devDependencies["@vitejs/devtools"] // "MISSING")
' packages/devtools/package.json
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/package.json` around lines 53 - 54, Remove the duplicate
`@vitejs/devtools` entry by keeping it only in "dependencies" and deleting it from
"devDependencies" in the package.json; locate the "dependencies" and
"devDependencies" objects (look for the "@vitejs/devtools" key currently present
in both) and remove the devDependencies entry so there is a single source of
truth under "dependencies" alongside "@vitejs/devtools-kit" which remains
unchanged.
🧹 Nitpick comments (1)
packages/devtools/src/runtime/plugins/view/client.ts (1)

59-84: Consider optional chaining for nested context property access.

While the if (ctx) guards handle the case where context is unavailable, the nested property access (ctx.docks, ctx.panel.store.value) could throw if the devtools-kit API shape changes in future versions.

🛡️ Optional: More defensive property access
 devtools: {
   toggle() {
     const ctx = getViteDevToolsContext()
-    if (ctx)
-      ctx.docks.toggleEntry('nuxt:devtools')
+    ctx?.docks?.toggleEntry?.('nuxt:devtools')
   },
   close() {
     const ctx = getViteDevToolsContext()
-    if (ctx)
-      ctx.panel.store.value.open = false
+    if (ctx?.panel?.store?.value != null)
+      ctx.panel.store.value.open = false
   },
   open() {
     const ctx = getViteDevToolsContext()
-    if (ctx) {
-      ctx.panel.store.value.open = true
-      ctx.docks.switchEntry('nuxt:devtools')
+    if (ctx?.panel?.store?.value != null) {
+      ctx.panel.store.value.open = true
+      ctx.docks?.switchEntry?.('nuxt:devtools')
     }
   },
   async navigate(path: string) {
     const ctx = getViteDevToolsContext()
-    if (ctx) {
-      ctx.panel.store.value.open = true
-      ctx.docks.switchEntry('nuxt:devtools')
+    if (ctx?.panel?.store?.value != null) {
+      ctx.panel.store.value.open = true
+      ctx.docks?.switchEntry?.('nuxt:devtools')
     }
     await client.hooks.callHook('host:action:navigate', path)
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/runtime/plugins/view/client.ts` around lines 59 - 84,
The methods toggle, close, open and navigate use getViteDevToolsContext() and
then access nested properties like ctx.docks.toggleEntry and
ctx.panel.store.value.open which could throw if the devtools-kit shape changes;
update these calls to use defensive optional chaining (e.g.,
ctx?.docks?.toggleEntry, ctx?.panel?.store?.value?.open) or short-circuit checks
after getViteDevToolsContext() to ensure each nested property exists before
calling or assigning, referencing the methods devtools.toggle, devtools.close,
devtools.open and devtools.navigate and the getViteDevToolsContext() call to
locate where to apply the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/devtools/package.json`:
- Around line 53-54: Remove the duplicate `@vitejs/devtools` entry by keeping it
only in "dependencies" and deleting it from "devDependencies" in the
package.json; locate the "dependencies" and "devDependencies" objects (look for
the "@vitejs/devtools" key currently present in both) and remove the
devDependencies entry so there is a single source of truth under "dependencies"
alongside "@vitejs/devtools-kit" which remains unchanged.

---

Nitpick comments:
In `@packages/devtools/src/runtime/plugins/view/client.ts`:
- Around line 59-84: The methods toggle, close, open and navigate use
getViteDevToolsContext() and then access nested properties like
ctx.docks.toggleEntry and ctx.panel.store.value.open which could throw if the
devtools-kit shape changes; update these calls to use defensive optional
chaining (e.g., ctx?.docks?.toggleEntry, ctx?.panel?.store?.value?.open) or
short-circuit checks after getViteDevToolsContext() to ensure each nested
property exists before calling or assigning, referencing the methods
devtools.toggle, devtools.close, devtools.open and devtools.navigate and the
getViteDevToolsContext() call to locate where to apply the changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9691fd0-12fa-4ead-be7e-35e4f9990657

📥 Commits

Reviewing files that changed from the base of the PR and between 112af4f and c7f3ab6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/devtools/package.json
  • packages/devtools/src/runtime/plugins/view/client.ts
  • pnpm-workspace.yaml

@antfu antfu merged commit 8807be5 into main Mar 18, 2026
3 of 5 checks passed
@antfu antfu deleted the antfu/use-vite-devtools-kit branch March 18, 2026 02:31
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.

2 participants