---
title: "Module Authors Guide"
description: "Add your own modules integration to the Nuxt DevTools."
canonical_url: "https://nuxt.com/modules/devtools/module-authors"
---
# Module Authors Guide

> Add your own modules integration to the Nuxt DevTools.

Nuxt DevTools is designed to be extensible. You can add your own modules integration to the DevTools.

Nuxt DevTools v4 is built on [Vite DevTools](https://github.com/vitejs/devtools): your module registers **dock entries** (tabs), **RPC functions** and **terminals** on the same hosts every other Vite tool uses, from one hook, [`onDevtoolsReady()`](https://nuxt.com/modules/devtools/utils-kit#ondevtoolsready). If your module still uses the v3 API (`addCustomTab`, `extendServerRpc`, …), see the [migration guide](https://nuxt.com/modules/devtools/module-migration).

## Starter Template

The [`module-starter` playground](https://github.com/nuxt/devtools/tree/main/playgrounds/module-starter) in the DevTools repo is a module with a fully custom view contributed as a tab, on the v4 API. Copy it to start your integration.

::note
The `module-devtools` template of `nuxi init` still targets the v3 API (`devtools:customTabs`). It keeps working through the compatibility shims, but prints deprecation warnings.
::

## Contributing to View

Most integrations contribute an `iframe` view: serve your module's view yourself, then register it as a dock entry in the `Nuxt` group. Vite DevTools also supports `launcher`, `action` and `json-render` entries.

```ts
import { NUXT_DEVTOOLS_GROUP_ID, onDevtoolsReady } from '@nuxt/devtools-kit'

onDevtoolsReady((ctx) => {
  ctx.docks.register({
    // unique identifier
    id: 'my-module',
    // title to display in the dock
    title: 'My Module',
    // any icon from Iconify, or a URL to an image
    icon: 'carbon:apps',
    // iframe view
    type: 'iframe',
    url: '/url-to-your-module-view',
    // show it inside the `Nuxt` group, next to the built-in tabs
    groupId: NUXT_DEVTOOLS_GROUP_ID,
  })
})
```

Set `category` (`app`, `analyze`, `server`, `modules`, `documentation`, `advanced`) to choose the section of the `Nuxt` group the entry appears in, or omit `groupId` to register a top-level dock next to Vue DevTools and Vite Inspect.

`register()` returns a handle to patch the entry later, for example to show a badge:

```ts
onDevtoolsReady((ctx) => {
  const entry = ctx.docks.register({ id: 'my-module', /* ... */ })
  entry.update({ badge: '3' })
})
```

Learn more about [DevTools Utility Kit](https://nuxt.com/modules/devtools/utils-kit).

## Lazy Service Launching

If the view you are contributing is heavy to load, register a `launcher` entry first and swap it for the iframe once the user starts it. Re-registering the same `id` with `true` as the second argument replaces the entry:

```ts
let promise: Promise<void> | undefined

onDevtoolsReady((ctx) => {
  ctx.docks.register({
    id: 'my-module',
    title: 'My Module',
    icon: 'carbon:apps',
    type: 'launcher',
    groupId: NUXT_DEVTOOLS_GROUP_ID,
    launcher: {
      title: 'Start My Module',
      description: 'Starts the inspector server on demand.',
      async onLaunch() {
        promise ||= launchService()
        await promise
        ctx.docks.register({
          id: 'my-module',
          title: 'My Module',
          icon: 'carbon:apps',
          type: 'iframe',
          url: '/url-to-your-module-view',
          groupId: NUXT_DEVTOOLS_GROUP_ID,
        }, true)
      },
    },
  })
})
```

It will first display a launch page with a button to start the service. When the user clicks the button, `onLaunch()` is called, and the entry becomes the iframe.

## Custom RPC Functions

Nuxt DevTools uses Remote Procedure Call (RPC) to communicate between the server and client. For modules you can also leverage that to communicate with your server code.

Scope the RPC host to your module so every function and event name is prefixed with your namespace (`my-module:` below) without repeating it:

```ts
import { onDevtoolsReady } from '@nuxt/devtools-kit'
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup(options, nuxt) {
    onDevtoolsReady((ctx) => {
      const { rpc } = ctx.scope('my-module')

      // register server RPC functions
      rpc.register({
        name: 'get-options',
        type: 'query',
        handler() {
          return options
        },
      })

      // call client RPC functions when something changes; `broadcast` reaches
      // every connected client (none are connected yet when this hook runs)
      nuxt.hook('builder:watch', (_event, path) => {
        rpc.broadcast({
          method: 'show-notification',
          args: [`${path} changed`],
          event: true
        })
      })
    })
  },
})
```

`type` is `'query'` for reads, `'action'` for mutations, `'event'` for fire-and-forget and `'static'` for values that never change.

And on the embedded iframe client side, connect to Vite DevTools and use the same scope:

```ts
import { getDevToolsRpcClient } from '@vitejs/devtools-kit/client'

const kit = await getDevToolsRpcClient()
const { rpc } = kit.scope('my-module')

// register client RPC functions
rpc.register({
  name: 'show-notification',
  type: 'event',
  handler(message: string) {
    console.log(message)
  },
})

// call server RPC functions
const options = await rpc.call('get-options')
```

See the [iframe client](https://nuxt.com/modules/devtools/utils-kit#nuxtdevtools-kitiframe-client) section for how to reach the user's app from your iframe.

## Trying Local Changes

You can clone Nuxt DevTools repo and try your changes locally.

Please refer to [Trying Local Changes](https://nuxt.com/modules/devtools/contributing#trying-local-changes).

## Examples

Here are a few examples of how to integrate Nuxt DevTools in modules:

- [Nuxt DevTools `module-starter` playground](https://github.com/nuxt/devtools/tree/main/playgrounds/module-starter), on the v4 API

These ones use the v3 API, which keeps working through the compatibility shims:

- [VueUse adds a docs tab](https://github.com/vueuse/vueuse/blob/ce28cef154489c73abe308104bef8568594a9bcd/packages/nuxt/index.ts#L89-L99)
- [UnoCSS Inspector](https://github.com/unocss/unocss/blob/25021a751494e99e85cfd82cca3855cdf78f6a12/packages/nuxt/src/index.ts#L81-L94)
- [Nuxt Test Utils](https://github.com/nuxt/test-utils/blob/fd024f45f752c2faa4c9e0cc1fc1f8b3eae59553/src/module.ts#L150-L192)
- [Nuxt OG Image Playground](https://github.com/nuxt-modules/og-image/blob/551b5474b44b8ff3190643e861c0b453813683b0/src/build/devtools.ts#L65-L80)
- [Nuxt Mongoose](https://github.com/arashsheyda/nuxt-mongoose/blob/89d50bd977de0f4edfdbe3ed150d0dca4d040709/src/devtools.ts#L38-L48)


## Sitemap

See the full [sitemap](https://nuxt.com/sitemap.md) for all pages.
