Utility Kit
Since v0.3.0, we are now providing a utility kit for easier DevTools integrations, similar to @nuxt/kit.
npm i @nuxt/devtools-kit
import { addCustomTab } from '@nuxt/devtools-kit'
We recommend module authors to install @nuxt/devtools-kit as a dependency and @nuxt/devtools as a dev dependency.
@nuxt/devtools-kit
addCustomTab()
addCustomTab() is soft-deprecated (NDT_DEP_0005) in favour of
registering a dock entry on the Vite DevTools docks host
(nuxt.devtools.docks.register(...)). It still works as a shim. Note the docks
host does not yet cover vnode views or tab categories. See the
migration guide.A shorthand for calling the hook devtools:customTabs.
import { addCustomTab } from '@nuxt/devtools-kit'
addCustomTab(() => ({
// unique identifier
name: 'my-module',
// title to display in the tab
title: 'My Module',
// any icon from Iconify, or a URL to an image
icon: 'carbon:apps',
// iframe view
view: {
type: 'iframe',
src: '/url-to-your-module-view',
},
}))
The iframe view supports the following options:
src: URL of the iframepersistent: Whether to persist the iframe instance when switching tabs (default:true)permissions: Additional permissions to allow in the iframe (merged with defaultclipboard-writeandclipboard-read)
const view: ModuleIframeView = {
type: 'iframe',
src: '/url-to-your-module-view',
persistent: true,
permissions: ['camera', 'microphone'],
}
refreshCustomTabs()
refreshCustomTabs() is soft-deprecated (NDT_DEP_0006). Update
dock entries directly via the handle returned by
nuxt.devtools.docks.register(...). It still works as a shim. See the
migration guide.A shorthand for call hook devtools:customTabs:refresh. It will refresh all custom tabs.
startSubprocess()
startSubprocess() is soft-deprecated (NDT_DEP_0004) in favour
of the Vite DevTools terminals host
(nuxt.devtools.terminals.startChildProcess(...)). It still works as a shim. See
the migration guide.Start a sub process using tinyexec and create a terminal tab in DevTools.
import { startSubprocess } from '@nuxt/devtools-kit'
const subprocess = startSubprocess(
{
command: 'code-server',
args: [
'serve-local',
'--accept-server-license-terms',
'--without-connection-token',
`--port=${port}`,
],
},
{
id: 'devtools:vscode',
name: 'VS Code Server',
icon: 'logos-visual-studio-code',
},
)
subprocess.restart()
subprocess.terminate()
extendServerRpc()
extendServerRpc() is soft-deprecated (NDT_DEP_0003) in favour
of the Vite DevTools RPC registration. It still works as a shim. See the
migration guide.Extend the server RPC with your own methods.
import { extendServerRpc } from '@nuxt/devtools-kit'
const rpc = extendServerRpc('my-module', {
async myMethod() {
return 'hello'
},
})
The forward path registers functions on the Vite DevTools RPC host from the
onDevtoolsReady() hook:
import { onDevtoolsReady } from '@nuxt/devtools-kit'
import { defineRpcFunction } from '@vitejs/devtools-kit'
export default defineNuxtModule({
setup(_options, nuxt) {
onDevtoolsReady((ctx) => {
ctx.rpc.register(defineRpcFunction({
name: 'my-module:my-method',
type: 'query',
setup: () => ({ handler: async () => 'hello' }),
}))
})
},
})
Learn more about Custom RPC functions.
onDevtoolsReady()
The recommended entry point for DevTools integration. The callback runs once
the Vite DevTools kit has connected and receives the connected
ViteDevToolsNodeContext, so the full devframe surface is guaranteed to be
available — no connect-safe buffering needed. Do all your DevTools integration here:
import { onDevtoolsReady } from '@nuxt/devtools-kit'
import { defineRpcFunction } from '@vitejs/devtools-kit'
export default defineNuxtModule({
setup(_options, nuxt) {
onDevtoolsReady((ctx) => {
// `ctx` is the connected ViteDevToolsNodeContext
ctx.docks.register({
id: 'my-module',
title: 'My Module',
type: 'iframe',
url: '/__my-module__/',
})
ctx.rpc.register(defineRpcFunction({
name: 'my-module:my-method',
type: 'query',
setup: () => ({ handler: async () => 'hello' }),
}))
ctx.messages.info('My module is ready')
})
},
})
It is backed by the devtools:ready Nuxt hook:
nuxt.hook('devtools:ready', (ctx) => {
// ...
})
Inside onDevtoolsReady(), the ctx is the connected ViteDevToolsNodeContext,
which exposes the full devframe-native surface:
ctx.docks— register dock entries (iframe / action / json-render / launcher)ctx.terminals— spawn and manage child processes / PTY sessionsctx.messages— structured messages and toast notificationsctx.commands— command-palette entriesctx.diagnostics— structured, coded diagnostics (powered by nostics)ctx.rpc— the devframe RPC host (register/invokeLocal/broadcast/sharedState/streaming/…)
If you need the raw context outside the hook, nuxt.devtools.devtoolsKit is
available as an escape hatch (it is undefined until the kit connects).
See the Vite DevTools Kit docs for the full host API.
Deprecation diagnostics
Nuxt DevTools emits coded deprecation diagnostics (NDT_DEP_xxxx) through
nostics. They print to the terminal and, once the Vite DevTools kit connects,
also surface in the DevTools diagnostics UI, each with a code, a fix, and a link
to the migration guide. See
extendServerRpc() and
startSubprocess().
devtools:notify hook
Push a notification into the unified devframe Messages system — the same
system that powers the Vite DevTools Messages dock and its toast overlay.
The notification is forwarded to ctx.messages, so no direct kit access is
needed, and calls made before the kit connects are buffered and replayed once
it does:
// server-side (module setup)
nuxt.callHook('devtools:notify', {
message: 'Something happened',
level: 'error', // 'info' | 'warn' | 'error' | 'success' | 'debug' (default 'info')
description: 'More details about what happened.',
notify: true, // also show a transient toast
})
Omit autoDelete for a persistent, leveled entry that builds history in the
Messages dock; set notify + autoDismiss + autoDelete for an ephemeral,
toast-only notification. From the client, the same input is available on the
injected client as client.devtools.notify(...).
@nuxt/devtools-kit/iframe-client
To provide complex interactions for your module integrations, we recommend to host your own view and display it in devtools via iframe.
To get the infomation from the devtools and the client app, you can do this in your client app:
import { useDevtoolsClient } from '@nuxt/devtools-kit/iframe-client'
export const devtoolsClient = useDevtoolsClient()
When the iframe been served with the same origin (CORS limitation), devtools will automatically inject __NUXT_DEVTOOLS__ to the iframe's window object. You can access it as a ref using useDevtoolsClient() utility.
onDevtoolsReady()
The client-side mirror of the server's onDevtoolsReady. The
callback runs once the Vite DevTools client is connected and receives the
DevToolsRpcClient (the same object as client.devtools.devtoolsKit), giving
full devframe-native access. This is the recommended way to register client RPC
functions:
import { onDevtoolsReady } from '@nuxt/devtools-kit/iframe-client'
onDevtoolsReady((kit) => {
kit.client.register({
name: 'my-module:on-update',
type: 'event',
handler: (payload) => {
// ...
},
})
})
useDevtoolsClient()
It will return a ref of NuxtDevtoolsIframeClient object that are intially null and will be updated when the connection is ready.
NuxtDevtoolsIframeClient contains two properties:
host: APIs to communicate with the main app in browserdevtools: APIs to communicate with the devtools
host can be undefined when devtools are accessed standalone or from a different origin.
For example, you can get the router instance from the client app:
const router = computed(() => devtoolsClient.value?.host?.nuxt.vueApp.config.globalProperties?.$router)
The devtools object also exposes devtoolsKit — the connected Vite DevTools
RPC client (mirroring nuxt.devtools.devtoolsKit on the server) — for full
devframe-native access. Use it to register client RPC functions, call server
functions, and more:
const kit = devtoolsClient.value?.devtools.devtoolsKit
kit?.client.register({
name: 'my-module:on-update',
type: 'event',
handler: (payload) => {
// ...
},
})
This replaces the deprecated devtools.extendClientRpc().
onDevtoolsClientConnected()
Similiar to useDevtoolsClient() but as a callback style:
import { onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client'
onDevtoolsClientConnected(async (client) => {
// client is NuxtDevtoolsIframeClient
const config = client.devtools.rpc.getServerConfig()
// ...
})
@nuxt/devtools-kit/host-client
When you have iframe for your devtools view, sometimes you need to communicate with the devtools host (the main app in browser) with a runtime plugin. You can use @nuxt/devtools-kit/host-client to do that.
useDevtoolsHostClient()
It will return a ref of NuxtDevtoolsHostClient object that are intially null and will be updated when the host is initialized by NuxtDevtools.
import { useDevtoolsHostClient } from '@nuxt/devtools-kit/host-client'
export default defineNuxtPlugin({
name: 'my-module:devtools',
setup(nuxtApp) {
const devtoolsHost = useDevtoolsHostClient()
// ...
}
})
onDevtoolsHostClientConnected()
Similiar to useDevtoolsHostClient() but as a callback style:
import { onDevtoolsHostClientConnected } from '@nuxt/devtools-kit/host-client'
onDevtoolsHostClientConnected(async (host) => {
})