Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Nuxt 4+ development patterns: server routes, file-based routing, middleware, composables, and h3 v1 / nitropack v2.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/middleware-plugins.md
1# Nuxt Middleware & Plugins23## When to Use45Working with `middleware/` or `plugins/` directories, route guards, app extensions.67## Route Middleware89Route middleware runs before navigation. Used for auth checks, redirects, logging.1011### Global Middleware1213Runs on every route change. **REQUIRED: Use `.global.ts` suffix:**1415```ts16// middleware/auth.global.ts17export default defineNuxtRouteMiddleware((to, from) => {18const auth = useAuthStore()1920if (to.meta.requiresAuth && !auth.isAuthenticated) {21return navigateTo('/login')22}23})24```2526**Without `.global.ts` suffix, middleware is named (not global).**2728## Red Flags - Stop and Check Skill2930If you're thinking any of these, STOP and re-read this skill:3132- "Suffix doesn't matter, it's about where I put it"33- "I'll redirect() instead of return navigateTo()"34- "I remember Nuxt 3 middleware patterns"35- "Export default function is simpler"3637All of these mean: You're using outdated patterns. Use Nuxt 4 patterns instead.3839### Named Middleware4041Runs only when explicitly applied. No `.global` suffix:4243```ts44// middleware/admin.ts45export default defineNuxtRouteMiddleware((to, from) => {46const auth = useAuthStore()4748if (!auth.isAdmin) {49return navigateTo('/')50}51})52```5354Apply in page:5556```vue57<script setup lang="ts">58definePageMeta({59middleware: ['admin']60})61</script>62```6364### Middleware Return Values6566```ts67export default defineNuxtRouteMiddleware((to, from) => {68// Allow navigation69return7071// Redirect72return navigateTo('/login')7374// Abort navigation75return abortNavigation()7677// Abort with error78return abortNavigation('Not authorized')79})80```8182### Middleware Order83841. Global middleware (alphabetical by filename)852. Layout middleware (if layout defines middleware)863. Page middleware (defined in definePageMeta)8788## Plugins8990Plugins extend Vue app with global functionality. Run during app initialization.9192### Basic Plugin9394```ts95// plugins/my-plugin.ts96export default defineNuxtPlugin((nuxtApp) => {97return {98provide: {99hello: (name: string) => `Hello ${name}!`100}101}102})103```104105Use in components:106107```vue108<script setup lang="ts">109const { $hello } = useNuxtApp()110console.log($hello('World')) // "Hello World!"111</script>112```113114### Plugin with Vue Plugin115116```ts117import type { PluginOptions } from 'vue-toastification'118// plugins/toast.client.ts119import Toast from 'vue-toastification'120import 'vue-toastification/dist/index.css'121122export default defineNuxtPlugin((nuxtApp) => {123nuxtApp.vueApp.use(Toast, {124position: 'top-right',125timeout: 3000126} as PluginOptions)127})128```129130### Plugin with Hooks131132```ts133// plugins/init.ts134export default defineNuxtPlugin((nuxtApp) => {135nuxtApp.hook('app:created', () => {136console.log('App created')137})138139nuxtApp.hook('page:finish', () => {140console.log('Page finished loading')141})142})143```144145### Client-Only or Server-Only146147Use file suffix:148149- `.client.ts` - runs only on client150- `.server.ts` - runs only on server151152```ts153// plugins/analytics.client.ts154export default defineNuxtPlugin(() => {155// Only runs in browser156if (window.analytics) {157window.analytics.init()158}159})160```161162### Plugin Order163164Use numeric prefix for execution order:165166```167plugins/168├── 01.first.ts169├── 02.second.ts170└── 03.third.ts171```172173### Async Plugins174175```ts176// plugins/api.ts177export default defineNuxtPlugin(async (nuxtApp) => {178const config = await fetch('/api/config').then(r => r.json())179180return {181provide: {182config183}184}185})186```187188## Best Practices189190**Middleware:**191192- **Return navigation or nothing** - don't mutate state heavily193- **Keep logic minimal** - delegate to composables/stores194- **Use for guards & redirects** only195- **Check meta properly** - `to.meta.requiresAuth`196- **Global = `.global.ts`** suffix required197198**Plugins:**199200- **Use for app-wide functionality** only201- **Provide via `provide`** for type safety202- **Consider client/server context** - use `.client`/`.server`203- **Minimize work** in plugin initialization204- **Use hooks** for lifecycle events205206## Common Mistakes207208| ❌ Wrong | ✅ Right |209| ------------------------------------ | ------------------------------------------------------------ |210| `export default function({ route })` | `export default defineNuxtRouteMiddleware((to, from) => {})` |211| Mutate route object | Return navigateTo() or nothing |212| `middleware/auth.ts` (not global) | `middleware/auth.global.ts` (global) |213| `redirect('/login')` | `return navigateTo('/login')` |214| Plugin without defineNuxtPlugin | Wrap in defineNuxtPlugin() |215216## Middleware Example: Auth217218```ts219// middleware/auth.global.ts220export default defineNuxtRouteMiddleware((to, from) => {221const auth = useAuthStore()222223// Public routes224const publicRoutes = ['/', '/login', '/register']225if (publicRoutes.includes(to.path)) {226return227}228229// Check auth230if (!auth.isAuthenticated) {231return navigateTo('/login')232}233234// Check role235if (to.meta.requiresAdmin && !auth.isAdmin) {236return abortNavigation('Access denied')237}238})239```240241## Plugin Example: API Client242243```ts244// plugins/api.ts245export default defineNuxtPlugin((nuxtApp) => {246const config = useRuntimeConfig()247248const api = $fetch.create({249baseURL: config.public.apiBase,250onRequest({ request, options }) {251const auth = useAuthStore()252if (auth.token) {253options.headers = {254...options.headers,255Authorization: `Bearer ${auth.token}`256}257}258},259onResponseError({ response }) {260if (response.status === 401) {261navigateTo('/login')262}263}264})265266return {267provide: {268api269}270}271})272```273274## Resources275276- Nuxt middleware: https://nuxt.com/docs/guide/directory-structure/middleware277- Nuxt plugins: https://nuxt.com/docs/guide/directory-structure/plugins278- Route middleware: https://nuxt.com/docs/getting-started/routing#route-middleware279