---
name: lifecycle-hooks
description: Nuxt and Nitro hooks for extending build-time and runtime behavior
---
# Lifecycle Hooks
Nuxt provides hooks to tap into the build process, application lifecycle, and server runtime.
## Build-time Hooks (Nuxt)
Used in `nuxt.config.ts` or modules:
### In nuxt.config.ts
```ts
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
'build:before': () => {
console.log('Build starting...')
},
'pages:extend': (pages) => {
// Add custom pages
pages.push({
name: 'custom',
path: '/custom',
file: '~/pages/custom.vue',
})
},
'components:dirs': (dirs) => {
// Add component directories
dirs.push({ path: '~/extra-components' })
},
},
})
```
### In Modules
```ts
// modules/my-module.ts
export default defineNuxtModule({
setup(options, nuxt) {
nuxt.hook('ready', async (nuxt) => {
console.log('Nuxt is ready')
})
nuxt.hook('close', async (nuxt) => {
console.log('Nuxt is closing')
})
nuxt.hook('modules:done', () => {
console.log('All modules loaded')
})
},
})
```
### Common Build Hooks
| Hook | When |
|------|------|
| `ready` | Nuxt initialization complete |
| `close` | Nuxt is closing |
| `modules:done` | All modules installed |
| `build:before` | Before build starts |
| `build:done` | Build complete |
| `pages:extend` | Pages routes resolved |
| `components:dirs` | Component dirs being resolved |
| `imports:extend` | Auto-imports being resolved |
| `nitro:config` | Before Nitro config finalized |
| `vite:extend` | Vite context created |
| `vite:extendConfig` | Before Vite config finalized |
## App Hooks (Runtime)
Used in plugins and composables:
### In Plugins
```ts
// plugins/lifecycle.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('app:created', (vueApp) => {
console.log('Vue app created')
})
nuxtApp.hook('app:mounted', (vueApp) => {
console.log('App mounted')
})
nuxtApp.hook('page:start', () => {
console.log('Page navigation starting')
})
nuxtApp.hook('page:finish', () => {
console.log('Page navigation finished')
})
nuxtApp.hook('page:loading:start', () => {
console.log('Page loading started')
})
nuxtApp.hook('page:loading:end', () => {
console.log('Page loading ended')
})
})
```
### Common App Hooks
| Hook | When |
|------|------|
| `app:created` | Vue app created |
| `app:mounted` | Vue app mounted (client only) |
| `app:error` | Fatal error occurred |
| `page:start` | Page navigation starting |
| `page:finish` | Page navigation finished |
| `page:loading:start` | Loading indicator should show |
| `page:loading:end` | Loading indicator should hide |
| `link:prefetch` | Link is being prefetched |
### Using Runtime Hooks
```ts
// composables/usePageTracking.ts
export function usePageTracking() {
const nuxtApp = useNuxtApp()
nuxtApp.hook('page:finish', () => {
trackPageView(useRoute().path)
})
}
```
## Server Hooks (Nitro)
Used in server plugins:
```ts
// server/plugins/hooks.ts
export default defineNitroPlugin((nitroApp) => {
// Modify HTML before sending
nitroApp.hooks.hook('render:html', (html, { event }) => {
html.head.push('')
html.bodyAppend.push('')
})
// Modify response
nitroApp.hooks.hook('render:response', (response, { event }) => {
console.log('Sending response:', response.statusCode)
})
// Before request
nitroApp.hooks.hook('request', (event) => {
console.log('Request:', event.path)
})
// After response
nitroApp.hooks.hook('afterResponse', (event) => {
console.log('Response sent')
})
})
```
### Common Nitro Hooks
| Hook | When |
|------|------|
| `request` | Request received |
| `beforeResponse` | Before sending response |
| `afterResponse` | After response sent |
| `render:html` | Before HTML is sent |
| `render:response` | Before response is finalized |
| `error` | Error occurred |
## Custom Hooks
### Define Custom Hook Types
```ts
// types/hooks.d.ts
import type { HookResult } from '@nuxt/schema'
declare module '#app' {
interface RuntimeNuxtHooks {
'my-app:event': (data: MyEventData) => HookResult
}
}
declare module '@nuxt/schema' {
interface NuxtHooks {
'my-module:init': () => HookResult
}
}
declare module 'nitropack/types' {
interface NitroRuntimeHooks {
'my-server:event': (data: any) => void
}
}
```
### Call Custom Hooks
```ts
// In a plugin
export default defineNuxtPlugin((nuxtApp) => {
// Call custom hook
nuxtApp.callHook('my-app:event', { type: 'custom' })
})
// In a module
export default defineNuxtModule({
setup(options, nuxt) {
nuxt.callHook('my-module:init')
},
})
```
## useRuntimeHook
Call hooks at runtime from components:
```vue
```
## Hook Examples
### Page View Tracking
```ts
// plugins/analytics.client.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('page:finish', () => {
const route = useRoute()
analytics.track('pageview', {
path: route.path,
title: document.title,
})
})
})
```
### Performance Monitoring
```ts
// plugins/performance.client.ts
export default defineNuxtPlugin((nuxtApp) => {
let navigationStart: number
nuxtApp.hook('page:start', () => {
navigationStart = performance.now()
})
nuxtApp.hook('page:finish', () => {
const duration = performance.now() - navigationStart
console.log(`Navigation took ${duration}ms`)
})
})
```
### Inject HTML
```ts
// server/plugins/inject.ts
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('render:html', (html) => {
html.head.push(`
`)
})
})
```