Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Route middleware

Route middleware is a function that runs before a page opens. It can let the navigation through, redirect to another address or cancel the navigation. A typical example is keeping guests out of the blog admin area.

Creating it

npx nuxi add middleware auth

The command creates app/middleware/auth.ts. Replace its content:

// app/middleware/auth.ts
export default defineNuxtRouteMiddleware(() => {
  const token = useCookie('token')
 
  if (!token.value) {
    return navigateTo('/login')
  }
})

useCookie('token') reads the cookie named token both on the server and in the browser. If there is no cookie, the function returns navigateTo('/login'), a redirect to the login page. If the function returns nothing, navigation continues.

Attaching it to a page

Middleware runs only where you list it. Add it to app/pages/admin.vue:

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

Open /admin: without a token cookie you are sent to /login. The child page /admin/comments is protected too, because it is shown inside admin.vue.

What middleware can return

ResultWhat happens
NothingThe page opens
navigateTo('/login')Redirect to another address
abortNavigation()Navigation is cancelled
abortNavigation('Access denied')Navigation is cancelled with an error

From and to

The function receives two routes: to, where the user is going, and from, where they come from:

// app/middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const token = useCookie('token')
 
  if (!token.value) {
    return navigateTo({ path: '/login', query: { back: to.fullPath } })
  }
})

Now the address becomes /login?back=/admin/comments, and after signing in the login page can send the user back where they came from.

Global middleware

If you add .global to the file name, the middleware runs on every navigation without being listed on a page:

// app/middleware/track.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`Navigation: ${from.fullPath} -> ${to.fullPath}`)
})

On the first load the message appears in the terminal running npm run dev; on later navigations it appears in the browser console. This shows that middleware runs both on the server and in the browser.

Common mistake

A global middleware that sends guests to /login also runs when going to /login itself. The result is an endless redirect, and the browser shows an error. Always let through the page you redirect to: if (to.path === '/login') return.

Thanks for reading!

Donate to the site — we work hard for you.