#Adding public assets from module

1 messages · Page 1 of 1 (latest)

lusty light
#

I want to add public assets in defineNuxtModule (v3)

valid hareBOT
#

Hi @lusty light. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

You can expose public assets from a Nuxt module by hooking into Nitro's configuration and adding a directory to publicAssets. Here's how to do it:

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
      })
    })
  },
})

Place your static files inside the runtime/public directory of your module. They will then be served as public assets in the application that installs your module. [Add Other Assets]

Note: createResolver(import.meta.url) is used to resolve paths relative to your module file, ensuring the correct directory is referenced regardless of where the module is installed.


Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@lusty light Kapa.ai is still learning and improving, please let me know how I did by reacting below.

lusty light
#

@valid hare The hook doesn't exist in my types

valid hareBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

The nitro:config hook is a standard Nuxt build-time hook and is listed in the official Nuxt lifecycle hooks documentation for both Nuxt 3 and Nuxt 4. [Nuxt Hooks]

If you're not seeing it in your types, this may be related to a known issue where the nitro types are not available in a clean environment before nuxt prepare has been run. Specifically, there have been reported bugs where Nitro-related types are only generated after nuxt prepare or nuxt build completes, causing type errors in fresh environments. [Type Error Issue]

A few things to try:

  1. Run nuxt prepare first to generate the .nuxt directory and its type declarations:

    npx nuxt prepare
    
  2. Ensure your @nuxt/kit and nuxt packages are up to date, as forward-compatible Nitro types were added in recent versions (see PR nuxt/nuxt#34036). [Related PRs]

  3. Check your TypeScript setup — the hook should be available via the NuxtHooks interface once the .nuxt types are generated.

After running nuxt prepare, the nitro:config hook should be recognized in your module's setup function.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@lusty light Kapa.ai is still learning and improving, please let me know how I did by reacting below.

lusty light
#

Show me a good typescript setup for a nuxt module library @valid hare

valid hareBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on the knowledge sources, here's a solid TypeScript setup for a Nuxt module library:

Module Definition

Use defineNuxtModule with the object syntax and proper TypeScript typing via the .with() method for fully typed resolved options:

// src/module.ts
import { addComponentsDir, addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'

// Define your module options interface
interface ModuleOptions {
  apiKey: string
  baseURL: string
  timeout?: number
}

export default defineNuxtModule<ModuleOptions>().with({
  meta: {
    name: '@my-org/my-module',
    configKey: 'myModule',
    compatibility: {
      nuxt: '>=3.0.0',
    },
  },
  defaults: {
    baseURL: '<https://api.example.com',>
    timeout: 5000,
  },
  setup (options, nuxt) {
    // options.baseURL and options.timeout are non-optional here
    const resolver = createResolver(import.meta.url)

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

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

[Module Anatomy; Type Safety]

Key TypeScript Practices

1. Use .with() for typed resolved options

Without .with(), optional properties like timeout would be typed as number | undefined even after defaults are applied. .with() makes TypeScript understand that defaults make those properties non-optional. [Type Safety]

2. Augment types by directory context

#

Place type declaration files in the correct directory for each type context: [Augment Types]

my-module/           # node type context
  runtime/           # app type context
    augments.app.d.ts
    server/          # server type context
      augments.server.d.ts
  module.ts
  augments.node.d.ts

3. Extend TypeScript config from your module if needed

setup (options, nuxt) {
  const resolve = createResolver(import.meta.url).resolve

  // Extend app tsconfig
  nuxt.options.typescript.tsConfig.include ??= []
  nuxt.options.typescript.tsConfig.include.push(resolve('./augments.d.ts'))

  // Extend server tsconfig
  nuxt.options.nitro.typescript ??= {}
  nuxt.options.nitro.typescript.tsConfig ??= {}
  nuxt.options.nitro.typescript.tsConfig.include ??= []
  nuxt.options.nitro.typescript.tsConfig.include.push(resolve('./augments.d.ts'))
}

[Extend TS Config]

4. Prefix all exports to avoid conflicts — e.g. <FooButton> not <Button>, /api/_foo/data not /api/data. [Best Practices]

5. Use nuxt/kit as a subpath import in local modules — you don't need to add @nuxt/kit as a separate dependency. [Local Modules]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: