Route Middleware
Running logic before a page renders — the pattern behind auth guards, redirects, and access checks.
អាន 2 នាទី
Some logic needs to run before a page is allowed to render — checking whether a user is logged in, redirecting an old URL to a new one, verifying a permission. Nuxt calls this route middleware: functions that run during navigation, before the destination page's component is mounted.
Defining middleware
A file in the middleware/ directory becomes middleware you can reference by name:
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const user = useUser(); // some composable holding the current user
if (!user.value) {
return navigateTo("/login");
}
});defineNuxtRouteMiddleware gives you the destination (to) and origin (from) routes, both the same Route objects useRoute() returns elsewhere. Returning navigateTo(...) redirects instead of continuing; returning nothing lets the navigation proceed.
Attaching it to a page
Named middleware has to be opted into per page with definePageMeta, the same mechanism used for layouts:
<!-- pages/dashboard.vue -->
<script setup>
definePageMeta({
middleware: "auth",
});
</script>A page can list more than one: middleware: ["auth", "subscription-check"], run in order.
Global middleware
Naming a file with a .global.ts suffix runs it on every navigation, with no opt-in needed — useful for things every page should have, like logging or a maintenance-mode check:
// middleware/analytics.global.ts
export default defineNuxtRouteMiddleware((to) => {
trackPageView(to.fullPath);
});Reach for global middleware sparingly — logic that only some pages need (like the auth example) belongs as named middleware attached where it's actually required, so it's obvious from a page's own file which rules apply to it.
Why this runs differently from a plain onMounted check
Doing an auth check inside onMounted in the page component has a real gap during SSR: the server would render the full protected page's HTML — including any data fetched during SSR — before the client-side check ever runs and redirects. That's a real leak of data the user was never supposed to see, if only briefly. Route middleware, by contrast, runs as part of the navigation itself, both on the server during SSR and client-side, so a redirect happens before the protected page's useFetch calls or template ever execute.
Middleware is one part of a fuller auth setup — you'd typically pair it with a server/ route or middleware that actually validates a session token — but it's the piece responsible for keeping a logged-out user from ever seeing a protected page's rendered output.