Make your Nuxt experience count in The State of JavaScript 2024

Custom Routing

In Nuxt 3, your routing is defined by the structure of your files inside the pages directory. However, since it uses vue-router under the hood, Nuxt offers you several ways to add custom routes in your project.

Adding custom routes

In Nuxt 3, your routing is defined by the structure of your files inside the pages directory. However, since it uses vue-router under the hood, Nuxt offers you several ways to add custom routes in your project.

Router Config

Using router options, you can optionally override or extend your routes using a function that accepts the scanned routes and returns customized routes.

If it returns null or undefined, Nuxt will fall back to the default routes (useful to modify input array).

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'

export default {
  // https://router.vuejs.org/api/interfaces/routeroptions.html#routes
  routes: (_routes) => [
    {
      name: 'home',
      path: '/',
      component: () => import('~/pages/home.vue')
    }
  ],
} satisfies RouterConfig
Nuxt will not augment any new routes you return from the routes function with metadata defined in definePageMeta of the component you provide. If you want that to happen, you should use the pages:extend hook which is called at build-time.

Pages Hook

You can add, change or remove pages from the scanned routes with the pages:extend nuxt hook.

For example, to prevent creating routes for any .ts files:

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

export default defineNuxtConfig({
  hooks: {
    'pages:extend' (pages) {
      // add a route
      pages.push({
        name: 'profile',
        path: '/profile',
        file: '~/extra-pages/profile.vue'
      })

      // remove routes
      function removePagesMatching (pattern: RegExp, pages: NuxtPage[] = []) {
        const pagesToRemove: NuxtPage[] = []
        for (const page of pages) {
          if (page.file && pattern.test(page.file)) {
            pagesToRemove.push(page)
          } else {
            removePagesMatching(pattern, page.children)
          }
        }
        for (const page of pagesToRemove) {
          pages.splice(pages.indexOf(page), 1)
        }
      }
      removePagesMatching(/\.ts$/, pages)
    }
  }
})

Nuxt Module

If you plan to add a whole set of pages related with a specific functionality, you might want to use a Nuxt module.

The Nuxt kit provides a few ways to add routes:

Router Options

On top of customizing options for vue-router, Nuxt offers additional options to customize the router.

Using app/router.options

This is the recommended way to specify router options.

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'

export default {
} satisfies RouterConfig

It is possible to add more router options files by adding files within the pages:routerOptions hook. Later items in the array override earlier ones.

Adding a router options file in this hook will switch on page-based routing, unless optional is set, in which case it will only apply when page-based routing is already enabled.
nuxt.config.ts
import { createResolver } from '@nuxt/kit'

export default defineNuxtConfig({
  hooks: {
    'pages:routerOptions' ({ files }) {
      const resolver = createResolver(import.meta.url)
      // add a route
      files.push({
        path: resolver.resolve('./runtime/app/router-options'),
        optional: true
      })
    }
  }
})

Using nuxt.config

Note: Only JSON serializable options are configurable:

  • linkActiveClass
  • linkExactActiveClass
  • end
  • sensitive
  • strict
  • hashMode
  • scrollBehaviorType
nuxt.config
export default defineNuxtConfig({
  router: {
    options: {}
  }
})

Hash Mode (SPA)

You can enable hash history in SPA mode using the hashMode config. In this mode, router uses a hash character (#) before the actual URL that is internally passed. When enabled, the URL is never sent to the server and SSR is not supported.

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
  router: {
    options: {
      hashMode: true
    }
  }
})

You can optionally customize the scroll behavior for hash links. When you set the config to be smooth and you load a page with a hash link (e.g. https://example.com/blog/my-article#comments), you will see that the browser smoothly scrolls to this anchor.

nuxt.config.ts
export default defineNuxtConfig({
  router: {
    options: {
      scrollBehaviorType: 'smooth'
    }
  }
})

Custom History (advanced)

You can optionally override history mode using a function that accepts the base URL and returns the history mode. If it returns null or undefined, Nuxt will fallback to the default history.

app/router.options.ts
import type { RouterConfig } from '@nuxt/schema'
import { createMemoryHistory } from 'vue-router'

export default {
  // https://router.vuejs.org/api/interfaces/routeroptions.html
  history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
} satisfies RouterConfig