# Source: https://nuxt.com/raw/docs/3.x/guide/modules/recipes-basics.md

# Source: https://nuxt.com/raw/docs/4.x/guide/modules/recipes-basics.md

# Add Plugins, Components & More

> Learn how to inject plugins, components, composables and server routes from your module.

Here are some common patterns used by module authors.

## Modify Nuxt Configuration

Nuxt configuration can be read and altered by modules. Here's an example of a module enabling an experimental feature.

```js
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    // We create the `experimental` object if it doesn't exist yet
    nuxt.options.experimental ||= {}
    nuxt.options.experimental.componentIslands = true
  },
})
```

When you need to handle more complex configuration alterations, you should consider using [defu](https://github.com/unjs/defu).

<tip icon="i-lucide-video" target="_blank" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options?friend=nuxt">

Watch Vue School video about altering Nuxt configuration.

</tip>

## Expose Options to Runtime

Because modules aren't part of the application runtime, their options aren't either. However, in many cases, you might need access to some of these module options within your runtime code. We recommend exposing the needed config using Nuxt's [`runtimeConfig`](/docs/4.x/api/nuxt-config#runtimeconfig).

```js
import { defineNuxtModule } from '@nuxt/kit'
import { defu } from 'defu'

export default defineNuxtModule({
  setup (options, nuxt) {
    nuxt.options.runtimeConfig.public.myModule = defu(nuxt.options.runtimeConfig.public.myModule, {
      foo: options.foo,
    })
  },
})
```

Note that we use [`defu`](https://github.com/unjs/defu) to extend the public runtime configuration the user provides instead of overwriting it.

You can then access your module options in a plugin, component, the application like any other runtime configuration:

```js
import { useRuntimeConfig } from '@nuxt/kit'

const options = useRuntimeConfig().public.myModule
```

<warning>

Be careful not to expose any sensitive module configuration on the public runtime config, such as private API keys, as they will end up in the public bundle.

</warning>

<read-more to="/docs/4.x/guide/going-further/runtime-config">



</read-more>

<tip icon="i-lucide-video" target="_blank" to="https://vueschool.io/lessons/passing-and-exposing-module-options?friend=nuxt">

Watch Vue School video about passing and exposing Nuxt module options.

</tip>

## Add Plugins

Plugins are a common way for a module to add runtime logic. You can use the `addPlugin` utility to register them from your module.

```js
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    // Create resolver to resolve relative paths
    const resolver = createResolver(import.meta.url)

    addPlugin(resolver.resolve('./runtime/plugin'))
  },
})
```

<read-more to="/docs/4.x/guide/going-further/kit">



</read-more>

## Add Components

If your module should provide Vue components, you can use the `addComponent` utility to add them as auto-imports for Nuxt to resolve.

```tstwoslash
import { addComponent, createResolver, defineNuxtModule, useRuntimeConfig } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    // From the runtime directory
    addComponent({
      name: 'MySuperComponent', // name of the component to be used in vue templates
      export: 'MySuperComponent', // (optional) if the component is a named (rather than default) export
      filePath: resolver.resolve('runtime/app/components/MySuperComponent.vue'),
    })

    // From a library
    addComponent({
      name: 'MyAwesomeComponent', // name of the component to be used in vue templates
      export: 'MyAwesomeComponent', // (optional) if the component is a named (rather than default) export
      filePath: '@vue/awesome-components',
    })
  },
})
```

Alternatively, you can add an entire directory by using `addComponentsDir`.

```ts
import { addComponentsDir, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addComponentsDir({
      path: resolver.resolve('runtime/app/components'),
    })
  },
})
```

<tip icon="i-lucide-lightbulb">

It is highly recommended to prefix your exports to avoid conflicts with user code or other modules.

<read-more to="/docs/4.x/guide/modules/best-practices#prefix-your-exports">



</read-more>
</tip>

<note>

Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.

</note>

## Add Composables

If your module should provide composables, you can use the `addImports` utility to add them as auto-imports for Nuxt to resolve.

```ts
import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addImports({
      name: 'useComposable', // name of the composable to be used
      as: 'useMyComposable', // optional alias that will be available for the consuming apps
      from: resolver.resolve('runtime/app/composables/useComposable'), // path of composable
    })
  },
})
```

Multiple entries can be passed as an array:

```ts
import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addImports([
      { name: 'useFirstComposable', from: resolver.resolve('runtime/composables/useFirstComposable') },
      { name: 'useSecondComposable', from: resolver.resolve('runtime/composables/useSecondComposable') },
    ])
  },
})
```

Alternatively, you can add an entire directory by using `addImportsDir`.

```ts
import { addImportsDir, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addImportsDir(resolver.resolve('runtime/composables'))
  },
})
```

<tip icon="i-lucide-lightbulb">

It is highly recommended to prefix your exports to avoid conflicts with user code or other modules.

<read-more to="/docs/4.x/guide/modules/best-practices#prefix-your-exports">



</read-more>
</tip>

<note>

Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.

</note>

## Add Server Routes

```ts
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addServerHandler({
      route: '/api/_my-module/hello',
      handler: resolver.resolve('./runtime/server/api/hello/index.get'),
    })
  },
})
```

You can also add a dynamic server route:

```ts
import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    addServerHandler({
      route: '/api/_my-module/hello/:name',
      handler: resolver.resolve('./runtime/server/api/hello/[name].get'),
    })

    // Or using a catch all route
    addServerHandler({
      route: '/api/_my-module/files/**:path',
      handler: resolver.resolve('./runtime/server/api/files/[...path].get'),
    })
  },
})
```

<tip icon="i-lucide-lightbulb">

It is highly recommended to prefix your server routes to avoid conflicts with user-defined routes. Common paths like `/api/auth`, `/api/login`, or `/api/user` may already be used by the application.

<read-more to="/docs/4.x/guide/modules/best-practices#prefix-your-exports">



</read-more>
</tip>

## Add Other Assets

If your module should provide other kinds of assets, they can also be injected. Here's a simple example module injecting a stylesheet through Nuxt's `css` array.

```js
import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    nuxt.options.css.push(resolver.resolve('./runtime/style.css'))
  },
})
```

And a more advanced one, exposing a folder of assets through [Nitro](/docs/4.x/guide/concepts/server-engine)'s `publicAssets` option:

```js
import { createResolver, defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup (options, nuxt) {
    const resolver = createResolver(import.meta.url)

    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.publicAssets ||= []
      nitroConfig.publicAssets.push({
        dir: resolver.resolve('./runtime/public'),
        maxAge: 60 * 60 * 24 * 365, // 1 year
      })
    })
  },
})
```

## Use Other Modules

If your module depends on other modules, you can specify them using the `moduleDependencies` option. This provides a more robust way to handle module dependencies with version constraints and configuration merging:

```ts
import { createResolver, defineNuxtModule } from '@nuxt/kit'

const resolver = createResolver(import.meta.url)

export default defineNuxtModule<ModuleOptions>({
  meta: {
    name: 'my-module',
  },
  moduleDependencies: {
    '@nuxtjs/tailwindcss': {
      // You can specify a version constraint for the module
      version: '>=6',
      // Any configuration that should override `nuxt.options`
      overrides: {
        exposeConfig: true,
      },
      // Any configuration that should be set. It will override module defaults but
      // will not override any configuration set in `nuxt.options`
      defaults: {
        config: {
          darkMode: 'class',
          content: {
            files: [
              resolver.resolve('./runtime/components/**/*.{vue,mjs,ts}'),
              resolver.resolve('./runtime/*.{mjs,js,ts}'),
            ],
          },
        },
      },
    },
  },
  setup (options, nuxt) {
    // We can inject our CSS file which includes Tailwind's directives
    nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
  },
})
```

<callout type="info">

The `moduleDependencies` option replaces the deprecated `installModule` function and ensures proper setup order and configuration merging.

</callout>