File System Routing

Nuxt.js automatically generates the vue-router configuration based on your file tree of Vue files inside the pages directory. When you create a .vue file in your pages directory you will have basic routing working with no extra configuration needed.

Sometimes you might need to create dynamic routes or nested routes or you might need to further configure the router property. This chapter will go through everything you need to know in order to get the best out of your router.

Nuxt.js gives you automatic code splitting for your routes, no configuration is needed

Use the NuxtLink component to navigate between pages

<template>
  <NuxtLink to="/">Home page</NuxtLink>
</template>

Basic Routes

This file tree:

pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue

will automatically generate:

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'user',
      path: '/user',
      component: 'pages/user/index.vue'
    },
    {
      name: 'user-one',
      path: '/user/one',
      component: 'pages/user/one.vue'
    }
  ]
}

Dynamic Routes

Sometimes it is not possible to know the name of the route such as when we make a call to an api to get a list of users or blog posts. We call these dynamic routes. To create a dynamic route you need to add an underscore before the .vue file name or before the name of the directory. You can name the file or directory anything you want but you must prefix it with an underscore.

This file tree:

pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

will automatically generate:

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'users-id',
      path: '/users/:id?',
      component: 'pages/users/_id.vue'
    },
    {
      name: 'slug',
      path: '/:slug',
      component: 'pages/_slug/index.vue'
    },
    {
      name: 'slug-comments',
      path: '/:slug/comments',
      component: 'pages/_slug/comments.vue'
    }
  ]
}

As you can see the route named users-id has the path :id? which makes it optional, if you want to make it required, create an index.vue file in the users/_id directory instead.

As of Nuxt >= v2.13 there is a crawler installed that will now crawl your link tags and generate your dynamic routes based on those links. However if you have pages that are not linked to such as a secret page, then you will need to manually generate those dynamic routes.

Generate dynamic routes for static sites

Locally Accessing Route Params

You can access the current route parameters within your local page or component by referencing this.$route.params.{parameterName}. For example, if you had a dynamic users page (users\_id.vue) and wanted to access the id parameter to load the user or process information, you could access the variable like this: this.$route.params.id.

Nested Routes

Nuxt.js lets you create nested routes by using the children routes of vue-router. To define the parent component of a nested route, you need to create a Vue file with the same name as the directory which contains your children views.

Don't forget to include the NuxtChild component inside the parent component (.vue file).

This file tree:

pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue

will automatically generate:

router: {
  routes: [
    {
      path: '/users',
      component: 'pages/users.vue',
      children: [
        {
          path: '',
          component: 'pages/users/index.vue',
          name: 'users'
        },
        {
          path: ':id',
          component: 'pages/users/_id.vue',
          name: 'users-id'
        }
      ]
    }
  ]
}

Dynamic Nested Routes

This is not a common scenario, but it is possible with Nuxt.js to have dynamic children inside dynamic parents.

This file tree:

pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

will automatically generate:

router: {
  routes: [
    {
      path: '/',
      component: 'pages/index.vue',
      name: 'index'
    },
    {
      path: '/:category',
      component: 'pages/_category.vue',
      children: [
        {
          path: '',
          component: 'pages/_category/index.vue',
          name: 'category'
        },
        {
          path: ':subCategory',
          component: 'pages/_category/_subCategory.vue',
          children: [
            {
              path: '',
              component: 'pages/_category/_subCategory/index.vue',
              name: 'category-subCategory'
            },
            {
              path: ':id',
              component: 'pages/_category/_subCategory/_id.vue',
              name: 'category-subCategory-id'
            }
          ]
        }
      ]
    }
  ]
}

Unknown Dynamic Nested Routes

If you do not know the depth of your URL structure, you can use _.vue to dynamically match nested paths. This will handle requests that do not match a more specific request.

This file tree:

pages/
--| people/
-----| _id.vue
-----| index.vue
--| _.vue
--| index.vue

Will handle requests like this:

/ -> index.vue
/people -> people/index.vue
/people/123 -> people/_id.vue
/about -> _.vue
/about/careers -> _.vue
/about/careers/chicago -> _.vue

Handling 404 pages is now up to the logic of the _.vue page.

Extending the router

There are multiple ways to extend the routing with Nuxt:

The router Property

The router property lets you customize the Nuxt.js router (vue-router).

nuxt.config.js
export default {
  router: {
    // customize the Nuxt.js router
  }
}

Base:

The base URL of the app. For example, if the entire single page application is served under /app/, then base should use the value '/app/'.

extendRoutes

You may want to extend the routes created by Nuxt.js. You can do so via the extendRoutes option.

Example of adding a custom route:

nuxt.config.js
export default {
  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        name: 'custom',
        path: '*',
        component: resolve(__dirname, 'pages/404.vue')
      })
    }
  }
}

If you want to sort your routes, you can use the  sortRoutes(routes)  function from @nuxt/utils:

nuxt.config.js
import { sortRoutes } from '@nuxt/utils'
export default {
  router: {
    extendRoutes(routes, resolve) {
      // Add some routes here ...

      // and then sort them
      sortRoutes(routes)
    }
  }
}

The schema of the route should respect the vue-router schema.

When adding routes that use Named Views, don't forget to add the corresponding chunkNames of named components.

nuxt.config.js
export default {
  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        path: '/users/:id',
        components: {
          default: resolve(__dirname, 'pages/users'), // or routes[index].component
          modal: resolve(__dirname, 'components/modal.vue')
        },
        chunkNames: {
          modal: 'components/modal'
        }
      })
    }
  }
}

fallback

Controls whether the router should fallback to hash mode when the browser does not support history.pushState but mode is set to history.

mode

Configure the router mode, it is not recommended to change it due to server-side rendering.

parseQuery / stringifyQuery

Provide custom query string parse / stringify functions.

routeNameSplitter

You may want to change the separator between route names that Nuxt.js uses. You can do so via the routeNameSplitter option in your configuration file. Imagine we have the page file pages/posts/_id.vue. Nuxt.js will generate the route name programmatically, in this case posts-id. Changing the routeNameSplitter config to / the name will therefore change to posts/id.

nuxt.config.js
export default {
  router: {
    routeNameSplitter: '/'
  }
}

scrollBehavior

The scrollBehavior option lets you define a custom behavior for the scroll position between the routes. This method is called every time a page is rendered.

To learn more about it, see vue-router scrollBehavior documentation.

Available since:v2.9.0:

In Nuxt.js you can use a file to overwrite the router scrollBehavior. This file should be placed in a folder called app.

~/app/router.scrollBehavior.js.

Example of forcing the scroll position to the top for every route:

app/router.scrollBehavior.js
export default function (to, from, savedPosition) {
  return { x: 0, y: 0 }
}

trailingSlash

Available since: v2.10

If this option is set to true, trailing slashes will be appended to every route. If set to false, they'll be removed.

nuxt.config.js
export default {
  router: {
    trailingSlash: true
  }
}

This option should not be set without preparation and has to be tested thoroughly. When setting router.trailingSlash to something else other than undefined(which is the default value), the opposite route will stop working. Thus 301 redirects should be in place and your internal linking has to be adapted correctly. If you set trailingSlash to true, then only example.com/abc/ will work but not example.com/abc. On false, it's vice-versa.