0
# Module Development
1
2
The module system in @nuxt/schema provides comprehensive type definitions for developing type-safe Nuxt modules, including module metadata, setup functions, dependency management, and compatibility checking.
3
4
## Core Module Types
5
6
### NuxtModule Interface
7
8
The main interface for creating Nuxt modules with full type safety.
9
10
```typescript { .api }
11
interface NuxtModule<
12
TOptions extends ModuleOptions = ModuleOptions,
13
TOptionsDefaults extends Partial<TOptions> = Partial<TOptions>,
14
TWith extends boolean = false,
15
> {
16
(
17
this: void,
18
resolvedOptions: TWith extends true
19
? ResolvedModuleOptions<TOptions, TOptionsDefaults>
20
: TOptions,
21
nuxt: Nuxt
22
): ModuleSetupReturn
23
24
getOptions?: (
25
inlineOptions?: Partial<TOptions>,
26
nuxt?: Nuxt
27
) => Promise<
28
TWith extends true
29
? ResolvedModuleOptions<TOptions, TOptionsDefaults>
30
: TOptions
31
>
32
33
getModuleDependencies?: (nuxt: Nuxt) => ModuleDependencies | undefined
34
}
35
36
type ModuleSetupReturn = Awaitable<false | void | ModuleSetupInstallResult>
37
type Awaitable<T> = T | Promise<T>
38
```
39
40
### ModuleMeta Interface
41
42
Metadata for module identification and compatibility.
43
44
```typescript { .api }
45
interface ModuleMeta {
46
/** Module name */
47
name?: string
48
/** Module version */
49
version?: string
50
/** Configuration key used within nuxt.config */
51
configKey?: string
52
/** Version constraints for Nuxt or features */
53
compatibility?: NuxtCompatibility
54
/** @internal Fully resolved path */
55
rawPath?: string
56
[key: string]: unknown
57
}
58
```
59
60
### Module Options and Results
61
62
```typescript { .api }
63
type ModuleOptions = Record<string, any>
64
65
type ModuleSetupInstallResult = {
66
/** Timing information for setup */
67
timings?: {
68
/** Total setup time in ms */
69
setup?: number
70
[key: string]: number | undefined
71
}
72
}
73
74
type ModuleSetupReturn = void | ModuleSetupInstallResult | Promise<void | ModuleSetupInstallResult>
75
76
interface ResolvedModuleOptions<T = ModuleOptions> {
77
src?: string
78
handler: T
79
options?: ModuleOptions
80
}
81
```
82
83
## Module Dependencies
84
85
### ModuleDependencies Interface
86
87
```typescript { .api }
88
interface ModuleDependencies {
89
[packageName: string]: ModuleDependencyMeta
90
}
91
92
interface ModuleDependencyMeta {
93
/** Dependency version requirement */
94
version?: string
95
/** Whether dependency is optional */
96
optional?: boolean
97
/** Custom installation instructions */
98
installCommand?: string
99
}
100
```
101
102
## Compatibility System
103
104
### NuxtCompatibility Interface
105
106
```typescript { .api }
107
interface NuxtCompatibility {
108
/** Required Nuxt version in semver format */
109
nuxt?: string
110
/** Builder compatibility requirements */
111
builder?: Partial<Record<'vite' | 'webpack' | 'rspack' | (string & {}), false | string>>
112
}
113
114
interface NuxtCompatibilityIssue {
115
name: string
116
message: string
117
}
118
119
interface NuxtCompatibilityIssues extends Array<NuxtCompatibilityIssue> {
120
/** Return formatted error message */
121
toString(): string
122
}
123
```
124
125
## Module Definition Patterns
126
127
### Basic Module
128
129
```typescript
130
import type { NuxtModule } from '@nuxt/schema';
131
import { defineNuxtModule } from '@nuxt/kit';
132
133
interface ModuleOptions {
134
apiKey?: string
135
timeout?: number
136
}
137
138
const myModule: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({
139
meta: {
140
name: 'my-module',
141
version: '1.0.0',
142
configKey: 'myModule',
143
compatibility: {
144
nuxt: '^3.0.0'
145
}
146
},
147
148
defaults: {
149
apiKey: '',
150
timeout: 5000
151
},
152
153
setup(options, nuxt) {
154
// Module setup logic
155
console.log('Module options:', options);
156
157
// Add runtime configuration
158
nuxt.options.runtimeConfig.myModule = {
159
apiKey: options.apiKey
160
};
161
162
// Register plugins
163
addPlugin({
164
src: path.resolve(__dirname, './runtime/plugin.client.ts'),
165
mode: 'client'
166
});
167
}
168
});
169
170
export default myModule;
171
```
172
173
### Advanced Module with Schema
174
175
```typescript
176
import type { NuxtModule } from '@nuxt/schema';
177
import { defineNuxtModule, createResolver, addImports } from '@nuxt/kit';
178
179
interface ModuleOptions {
180
enabled: boolean
181
providers: {
182
google?: {
183
clientId: string
184
clientSecret: string
185
}
186
github?: {
187
clientId: string
188
clientSecret: string
189
}
190
}
191
redirectUrl: string
192
}
193
194
const authModule: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({
195
meta: {
196
name: '@my-org/nuxt-auth',
197
version: '2.1.0',
198
configKey: 'auth',
199
compatibility: {
200
nuxt: '^3.8.0',
201
builder: {
202
vite: '^4.0.0',
203
webpack: false // Not compatible with webpack
204
}
205
}
206
},
207
208
defaults: {
209
enabled: true,
210
providers: {},
211
redirectUrl: '/auth/callback'
212
},
213
214
// JSON Schema for options validation
215
schema: {
216
type: 'object',
217
properties: {
218
enabled: { type: 'boolean' },
219
providers: {
220
type: 'object',
221
properties: {
222
google: {
223
type: 'object',
224
properties: {
225
clientId: { type: 'string' },
226
clientSecret: { type: 'string' }
227
},
228
required: ['clientId', 'clientSecret']
229
}
230
}
231
},
232
redirectUrl: { type: 'string' }
233
}
234
},
235
236
async setup(options, nuxt) {
237
if (!options.enabled) return;
238
239
const resolver = createResolver(import.meta.url);
240
241
// Add composables
242
addImports([
243
{
244
name: 'useAuth',
245
from: resolver.resolve('./runtime/composables/useAuth')
246
},
247
{
248
name: 'useAuthUser',
249
from: resolver.resolve('./runtime/composables/useAuthUser')
250
}
251
]);
252
253
// Add server middleware
254
addServerHandler({
255
route: '/api/auth/**',
256
handler: resolver.resolve('./runtime/server/auth.ts')
257
});
258
259
// Add type declarations
260
addTypeTemplate({
261
filename: 'types/auth.d.ts',
262
getContents: () => `
263
declare module '#app' {
264
interface NuxtApp {
265
$auth: {
266
user: Ref<User | null>
267
loggedIn: ComputedRef<boolean>
268
login: (provider: string) => Promise<void>
269
logout: () => Promise<void>
270
}
271
}
272
}
273
`
274
});
275
276
return {
277
timings: {
278
setup: performance.now()
279
}
280
};
281
}
282
});
283
```
284
285
### Module with Hooks
286
287
```typescript
288
const analyticsModule: NuxtModule = defineNuxtModule({
289
meta: {
290
name: 'nuxt-analytics',
291
version: '1.0.0'
292
},
293
294
hooks: {
295
'ready': async (nuxt) => {
296
console.log('Analytics module ready');
297
},
298
299
'build:before': async () => {
300
// Pre-build analytics setup
301
},
302
303
'render:route': async (url, result, context) => {
304
// Track page views
305
console.log(`Page rendered: ${url}`);
306
}
307
},
308
309
setup(options, nuxt) {
310
// Additional setup beyond hooks
311
nuxt.hook('app:resolve', async (app) => {
312
// Modify app configuration
313
app.head = app.head || {};
314
app.head.script = app.head.script || [];
315
app.head.script.push({
316
src: 'https://analytics.example.com/script.js',
317
async: true
318
});
319
});
320
}
321
});
322
```
323
324
## Module Utilities and Helpers
325
326
### Module Definition Helper
327
328
```typescript
329
function createModule<T = ModuleOptions>(
330
definition: Omit<NuxtModule<T>, 'setup'> & {
331
setup: (options: T, nuxt: Nuxt) => ModuleSetupReturn
332
}
333
): NuxtModule<T> {
334
return {
335
...definition,
336
setup: definition.setup
337
};
338
}
339
```
340
341
### Conditional Module Loading
342
343
```typescript
344
const conditionalModule: NuxtModule = defineNuxtModule({
345
meta: {
346
name: 'conditional-module'
347
},
348
349
setup(options, nuxt) {
350
// Only load in development
351
if (!nuxt.options.dev) {
352
return;
353
}
354
355
// Check for required dependencies
356
try {
357
require.resolve('some-dev-dependency');
358
} catch {
359
console.warn('Development dependency not found, skipping module');
360
return;
361
}
362
363
// Setup development features
364
addDevtools();
365
}
366
});
367
```
368
369
### Module with Runtime Dependencies
370
371
```typescript
372
interface DatabaseModuleOptions {
373
provider: 'postgres' | 'mysql' | 'sqlite'
374
connection: {
375
host?: string
376
port?: number
377
database: string
378
username?: string
379
password?: string
380
}
381
}
382
383
const databaseModule: NuxtModule<DatabaseModuleOptions> = defineNuxtModule({
384
meta: {
385
name: 'nuxt-database',
386
configKey: 'database'
387
},
388
389
async setup(options, nuxt) {
390
const resolver = createResolver(import.meta.url);
391
392
// Add required dependencies
393
await addBuildPlugin({
394
name: 'database-types',
395
setup(build) {
396
build.onResolve({ filter: /^#database$/ }, () => ({
397
path: resolver.resolve('./runtime/database'),
398
namespace: 'database'
399
}));
400
}
401
});
402
403
// Generate connection configuration
404
addTemplate({
405
filename: 'database.config.js',
406
getContents: () => `
407
export default ${JSON.stringify({
408
provider: options.provider,
409
connection: options.connection
410
}, null, 2)}
411
`
412
});
413
414
// Add database composables
415
addImports([
416
{ name: 'useDatabase', from: '#database' },
417
{ name: 'useQuery', from: '#database' }
418
]);
419
}
420
});
421
```
422
423
### Module Testing Pattern
424
425
```typescript
426
// tests/module.test.ts
427
import { describe, it, expect } from 'vitest';
428
import { setup, createPage } from '@nuxt/test-utils';
429
import type { NuxtModule } from '@nuxt/schema';
430
431
describe('My Module', async () => {
432
await setup({
433
nuxtConfig: {
434
modules: [
435
['./src/module', {
436
apiKey: 'test-key',
437
enabled: true
438
}]
439
]
440
}
441
});
442
443
it('should register composables', async () => {
444
const page = await createPage('/test');
445
446
const hasComposable = await page.evaluate(() => {
447
return typeof window.$nuxt?.$myModule !== 'undefined';
448
});
449
450
expect(hasComposable).toBe(true);
451
});
452
});
453
```
454
455
The module system provides a powerful foundation for extending Nuxt with full type safety, ensuring that modules integrate seamlessly with the Nuxt ecosystem while maintaining excellent developer experience.