You are reading the documentation for Vue Storefront v2. See the latest docs.

Layouts and Routing

Layouts and Routing in Vue Storefront are entirely powered by Nuxt.js. We will only give a brief overview of these features on this page, but you can learn more on the Views (opens new window) page in the Nuxt.js documentation.

View hierarchy

Every page consists of layers — some layers are shared between many routes, others are used in one specific route. We described each layer in detail in the sections below.

HTML document

At the root of the hierarchy is the HTML document. By default, the framework provides one, but you can customize it by creating an app.html file in the root directory of your project. It has special tags used to insert parts of the documents, and by default, looks like this:

<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
  <body {{ BODY_ATTRS }}>
    {{ APP }}


Nuxt.js automatically registers all .vue files inside of the layouts directory as layouts. Unless configured otherwise, pages use the default.vue component as their layout. Open the layouts/default.vue component to get the general idea of how the page looks like, what components it imports and what data it loads within the setup function.

Layout components include a special <Nuxt /> component that displays the page's content based on the current URL. Those pages are Vue.js components, too, explained in the next section.

There is also an error.vue layout — used when an error occurs. It doesn't use the <Nuxt /> component but receives the error prop, which you can use to get an error code or message.

The convention is to use lowercase when naming components inside of the layouts directory, e.g., blog.vue.


Nuxt.js automatically registers all .vue files inside the pages directory as application routes. For example, creating an AboutUs.vue component will create an /aboutus route. In the same way, creating this component inside a nested directory called company will create the /company/aboutus route. It's all thanks to the File System Routing (opens new window) feature available in Nuxt.js. In the sections below, we describe how to modify routes manually.

Pages can define a custom layout (opens new window) property to change the default used for this view.

The convention is to use PascalCase when naming components inside of the pages directory, e.g., MyAccount.vue.

Predefined routes

Every Vue Storefront project has a predefined list of routes injected by the @vue-storefront/nuxt-theme module. However, if you navigate the page, you might notice that the page routes don't match the name of the components inside the pages directory.

This is because internally, we use the extendRoutes (opens new window) function to create custom routes for some of the components that come out of the box.

Here's the map of routes and their corresponding components:

Route path Component (in the pages directory) Route name
/ Home.vue home
/p/:id/:slug/ Product.vue product
/c/:slug_1/:slug_2?/:slug_3?/:slug_4?/:slug_5? Category.vue category
/my-account/:pageName? MyAccount.vue my-account
/checkout Checkout.vue checkout
/checkout/shipping Checkout/Shipping.vue shipping
/checkout/billing Checkout/Billing.vue billing
/checkout/payment Checkout/Payment.vue payment
/checkout/thank-you Checkout/ThankYou.vue thank-you
/reset-password ResetPassword.vue reset-password

Manually adding and modifying routes

If you want to manually add your custom routes or modify some already provided, use the extendRoutes function in the nuxt.config.js. This function has two properties:

  • routes — an array of already registered routes. You can push or delete entries from it.
  • resolve — helper function for resolving Vue.js components based on their paths in the project.

For the sake of example, let's assume that we created a pages/AboutUs.vue component, but we want to use the /company/about-us route instead of auto-registered /aboutus. There are two approaches we could take.

The first approach is to delete existing route and register new route with a different path.

// nuxt.config.js

export default {
  router: {
    extendRoutes(routes, resolve) {
      // Delete automatically registered route
        routes.findIndex(route => route.path === '/AboutUs'),

      // Re-register the same component but with different path
        name: 'AboutUs',
        path: '/company/about-us',
        component: resolve(__dirname, 'pages/AboutUs.vue')

Alternatively, we can modify the path property of the existing entry like so:

// nuxt.config.js

export default {
  router: {
    extendRoutes(routes, resolve) {
      // Find route index
      const index = routes.findIndex(route => route.path === '/AboutUs');
      // Modify route path
      routes[index].path = '/company/about-us';

Changing base path

There are cases when your store is served under a specific path, eg. To make Vue.js router aware of this, you need to update the configuration in the nuxt.config.js:

// nuxt.config.js

export default {
  router: {
    base: "/shop/"

Unfortunately not all links in your application will detect this. You can fix it, by wrap all relative links and paths to assets in addBasePath helper.

  <SfImage :src="addBasePath('/imageA.webp')" />
  <SfBanner :image="addBasePath('/bannerB.png')" />

import { addBasePath } from '@vue-storefront/core';

export default {
  setup() {
    return {

To navigate between pages within your application, use the NuxtLink (opens new window) component, instead of the traditional <a> tag. While you can use the <a> tag for external links, using the <NuxtLink /> for internal links will ensure that you make use of the Single-Page Navigation capabilities that Nuxt.js provides.

Single-Page Navigation (SPA) provides many benefits, such as:

  • much faster and more responsive navigation compared to the traditional server navigation,
  • framework is initialized only once,
  • components shared between the pages are rendered only once (if they use the same layout),
  • fewer requests and data sent over the network.

What's next

Layouts and pages are one thing, but in the end, they must display components and styles. Otherwise, we would only serve blank pages.

New projects come with a default Theme, so the next step is to understand what makes it look like this.