#How to run a middleware for only a group route?

10 messages · Page 1 of 1 (latest)

barren trout
#

I've declared my middleware in index.vue under a group route. The middleware doesn't works and then I tried to rename the index with layout.vue (also it renders other pages under protected) . So is there any way to protect this route?
I thought defining index.vue for the entry of that group route will solve the issue and I can use my middleware to check for the all routes that comes under protected.

My goal: run a middleware only for the routes that is grouped names as (protected)

scenic echoBOT
#

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

#

To run middleware for only a group of routes (e.g., all routes under a directory like /protected), you should use a combination of Nuxt's file-based routing and the definePageMeta function to apply middleware at the group level.

How to do it:

  1. Use a layout for the group:
    If you want all routes under /protected to share middleware, you can create a custom layout (e.g., protected.vue in app/layouts/). Then, in each page under /protected, set the layout and middleware in definePageMeta:

    <!-- app/pages/protected/index.vue -->
    <script setup lang="ts">
    definePageMeta({
      layout: 'protected',
      middleware: 'auth'
    })
    </script>
    

    Repeat the middleware: 'auth' in each page under /protected.
    Note: Setting middleware in a layout file itself is not supported; middleware must be set in each page's definePageMeta or via the pages:extend hook.

  2. Automate with the pages:extend hook:
    To avoid repeating yourself, you can use the pages:extend hook in your nuxt.config.ts to programmatically add middleware to all pages under a certain directory:

    // nuxt.config.ts
    import type { NuxtPage } from 'nuxt/schema'
#

export default defineNuxtConfig({
hooks: {
'pages:extend'(pages) {
function setMiddleware(pages: NuxtPage[]) {
for (const page of pages) {
if (page.file?.includes('/protected/')) {
page.meta ||= {}
page.meta.middleware = ['auth']
}
if (page.children) {
setMiddleware(page.children)
}
}
}
setMiddleware(pages)
}
}
})

This will automatically apply the `auth` middleware to all pages under `/protected` without needing to set it manually in each file.  
[See example in the docs](<https://nuxt.com/docs/4.x/guide/directory-structure/app/middleware#setting-middleware-at-build-time>)

**Summary:**  
- Middleware must be set per-page, not in a group index or layout file.
- Use the `pages:extend` hook to programmatically apply middleware to a group of routes.
- Defining middleware in `index.vue` or `layout.vue` alone will not protect all child routes; each page must have the middleware set, or use the hook above to automate this.

For more details, see the official documentation: [Setting Middleware at Build Time](<https://nuxt.com/docs/4.x/guide/directory-structure/app/middleware#setting-middleware-at-build-time>) and [Page Metadata](<https://nuxt.com/docs/4.x/guide/directory-structure/app/pages#special-metadata>).
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
#

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

barren trout
#

Protected is group route like this (protected)

waxen summit
#

other than not being shown in the url

tame patio
#

Hi, Jawad!

Instead of relying on index.vue, define your middleware globally and then add it in the definePageMeta({ middleware: 'auth' }) of each page inside the protected/ directory.
Alternatively, you can create a layout (e.g. protected.vue in layouts/) and assign it to those routes so the middleware runs for all pages using that layout.

strong warren
#

You could also create a module that adds the route group information to the page meta:

import type { NuxtPage } from 'nuxt/schema'

import { defineNuxtModule } from 'nuxt/kit'

/**
 * Extracts the group name from the page file path, e.g., /(auth)/login -> 'auth'
 *
 * @param page - The NuxtPage object to extract the group from
 *
 * @returns The group name or undefined if not found
 */
function getGroup(page: NuxtPage) {
    return page.file?.match(/\([^)]+\)/)?.at(0)?.replaceAll(/[()]/g, '')
}

/**
 * Recursively sets the route group for each page based on its file path.
 *
 * @param pages - An array of NuxtPage objects to process
 */
function setPageGroup(pages: NuxtPage[]) {
    for (const page of pages) {
        const group = getGroup(page)

        if (group) {
            page.meta ||= {}
            page.meta.group = group
        }

        if (page.children) {
            setPageGroup(page.children)
        }
    }
}

export default defineNuxtModule({
    setup: (_, nuxt) => {
        nuxt.hook('pages:extend', pages => setPageGroup(pages))
    },
})

Then in your Nuxt route middleware, you can access the group:

export default defineNuxtRouteMiddleware((to) => {
    if (to.meta.group === 'protected') {
        // ... Your auth logic
    }
})