N
Nuxt3mo ago
Jawad

How to run a middleware for only a group route?

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)
6 Replies
kapa.ai
kapa.ai3mo ago
Hi @Jawad. 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>

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

// 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 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 and Page Metadata. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@758608011689459722> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Jawad
JawadOP3mo ago
Protected is group route like this (protected)
Cake
Cake2mo ago
route groups have no meaning in nuxt other than not being shown in the url
dario
dario2mo ago
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.
freb97
freb972mo ago
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))
},
})
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
}
})
export default defineNuxtRouteMiddleware((to) => {
if (to.meta.group === 'protected') {
// ... Your auth logic
}
})
There's also a PR open to add route groups to the page meta in general, so in future nuxt version you may be able to access them directly

Did you find this page helpful?