bg-img

Created by Maximilian Schwarzmüller
Last Updated on February 13, 2018

# Why all the Folders & Files Matter

In a new Nuxt.js project, you see many (empty) folders and files. Nuxt.js allows you to build Vue apps that are mainly configured through folders and files, so this directory structure makes a lot of sense.

It’s still interesting to understand what all these folders and files are about. Nuxt.js uses many folders and files. This article will explain the use of every single folder, but I won’t go through them alphabetically. Instead, I want to order them by importance and hence we’ll start with the pages folder.

Here’s a list of all the sections of this article, just in case you want to jump ahead:

# The “pages” Folder

Nuxt.js does one very important thing: It automatically creates routes for you. Behind the scenes, it still uses Vue Router for this but you don’t need to create a route config manually anymore.

Instead, you create your route structure as a folder structure - inside the pages folder.

For example, the following pages structure

pages / users / index.vue
index.vue

would translate to this route config:

;[
  { path: '/', component: 'pages/index.vue' },
  { path: '/users', component: 'pages/users/index.vue' },
]

Again: This uses the official Vue Router behind the scenes but it infers the route config from your folder structure.

You can also create dynamic routes (i.e. routes with a route parameter):

pages / users / index.vue
_id / index.vue
index.vue

This would yield the following route config:

;[
  { path: '/', component: 'pages/index.vue' },
  { path: '/users', component: 'pages/users/index.vue' },
  { path: '/users/:id', component: 'pages/users/_id/index.vue' },
]

In the pages/users/_id/index.vue component, you could then retrieve the id from the URL by accessing this.$route.params.id.

Yes, that’s exactly the same syntax you use in “normal” Vue apps.

There’s a bit more to the pages folder and how routing works in Nuxt.js. You can create nested dynamic routes or use _id.vue instead of _id/index.vue. But you can read all about that in the official docs on routing in Nuxt.js.

The core takeaway is, that routing is configured through folders and files in the pages folder. That’s the role of this folder and that’s why it’s a rather important one.

Due to this important role pages play, you can also add some special properties and methods to your page Vue component objects - I’ll highlight them throughout these articles. These special properties and methods will essentially be used by Nuxt.js and add extra functionalities to the components.

# The “components” Folder

You might’ve noticed that the pages folder contains .vue files. These are of course normal single component files as you know them from your ordinary Vue app.

And indeed, pages are just normal Vue components. They’re just loaded via the Vue router as explained in the “pages” section.

Of course you don’t build your entire Vue app by just using pages though. Or you shouldn’t do that at least.

You should instead leverage Vue’s strength of creating re-usable components to compose your UI from. You might have a <image-carousel> or a <custom-button> component which you want to use in one or more pages (or even nested in other re-usable components).

For such re-usable components, you got the components folder. There, you also store .vue files and you can of course create sub-directories.

But you import the components stored there to use them within your <template>, not to load them via the Vue router.

In Nuxt.js apps, you can load your re-usable components into other components or pages like this:

<script>
import CustomButton from '@/components/UI/CustomButton'

export default {
  components: {
    CustomButton
  }
}
</script>

This allows you to use <CustomButton /> (or <custom-button></custom-button>) in the template of that component.

Notice the @ sign in the import statement though. This is a feature provided by the Nuxt build process. @ simply refers to the project root path, so you can conveniently import from any subfolder of that path from anywhere in your app.

So instead of writing

import CustomButton from '../../components/UI/CustomButton'

inside some nested component or page, you can use that shorter syntax.

And that’s it. That’s the idea behind the components folder.

# The “layouts” Folder

There’s yet another folder in your Nuxt project that contains .vue files. The layouts folder. What’s that folder about then?

You got pages (in the pages folder), right? These are components that are loaded via the Vue Router.

Typically, these pages should use some layouts. Some wrapping component that provides shared UI elements like a header or footer. Without such a wrapping component, you’d have to add your header and footer components to each page separately.

That’s pretty cumbersome and no fun at all.

Layouts fix that problem. You can adjust the default layout (stored in the layouts/default.vue - don’t change that name!) or add your own layouts which you then use by adding a layout: 'my-layout' property to your page component object.

You can also create a default error page by creating a layouts/error.vue.

You can read more about layouts in the official docs.

# The “store” Folder

Enough about components! What about the app state? What about Vuex? Can you still use that in Nuxt apps?

The answer is: Yes, absolutely!

Nuxt.js actually comes with Vuex already installed. You have to “activate” it though. And how do you activate it? In the Nuxt.js way of course - you create some files in some folders. To be precise, you create an index.js file in the store folder (there actually is a second way - more on that below!).

By adding a store/index.js file, Vuex gets added to the app and you can start setting up mutations, actions etc in that file. More details about the syntax you should use can be found in the offical docs on Vuex in Nuxt.js apps.

I already mentioned, that there’s an alternative to adding a store/index.js file. And that’s adding multiple files to the store folder. Each file will then create a separate Vuex module - more details on that can be found here.

# The “assets” Folder

Your app typically doesn’t consist of just Vue components - though that’s of course possible.

Often you also have some images or global CSS files though. For such files, you got the assets folder.

Files stored in that folder can be imported into your Vue component files. An image could be included like this for example:

<script>
import NuxtLogo from '@/assets/images/nuxt-logo.jpg'

export default {
  data() {
    nuxtLogo: NuxtLogo
  }
}
</script>

You could then use it in the template like that:

<template>
  <img :src="nuxtLogo">
</template>

Alternatively, you could reference it like this (without the import in the <script> section):

<template>
  <img src="~assets/images/nuxt-logo.jpg">
</template>

Notice the ~ - it’s essentially the same as @: It references the root folder. In your <template> or <style> section, you have to use ~ instead of @ though.

This import is handled by Webpack - the build tool used behind the scenes.

It will basically find that image, potentially optimize it, and then copy it over into the folder that holds your build artifacts (where your compiled JS code will also end up in).

This processing of files only occurs for assets stored in the assets folder, hence that’s the place to use for most images, SCSS code etc.

You can read more about the assets folder here.

# The “static” Folder

We just had a look at the assets folder - it’s a great folder for storing images or other assets which should be processed by Webpack (the build-tool used by Nuxt.js behind the scenes).

Some assets shouldn’t be processed though. You might have some images which you don’t want to funnel through Webpack’s build process. You might have some CSS that’s good to use just as it is.

Such assets should go into the static folder. You won’t import them into your Vue components as you imported assets but instead you simply use them in your templates like this:

<template>
  <img src="my-image.png">
</template>

Here, my-image.png would be stored in static. Please note that you omit the path. You don’t import static/my-image.png - static assets are copied directly into your root folder and hence can be imported from there.

As always, you can read more in the official docs.

# The “middleware” Folder

Back to routing - that was the part done by creating components in the pages folder, you remember?

Whenever a route is loaded, Nuxt.js can execute some middleware. That’s essentially a function which is executed right before the target component for a given route is rendered to the screen.

The function is executed both on the client and the server - depending on whether you’re in your already-loaded app or you’re loading it for the first time.

What’s the use of middleware?

You can, for example, use it to check whether a user is allowed to enter a certain route/ page. You could check the user’s authentication status and redirect if he’s unauthenticated.

Here’s what a middleware function looks like in Nuxt.js:

export default function({ store }) {
  return store.getters.isAuth
}

This code would be put into a file in the middleware folder. Maybe the middleware/auth.js file.

You can then assign this middleware to all routes by adding it to the router config in your nuxt.config.js file (an example can be seen here) or to a specific layout (= group of pages) or single pages.

You assign a middleware to layouts and pages by adding the special middleware property to the Vue component objects:

<script>
  export default {
    middleware: 'auth' // or ['auth'] to assign multiple middlewares
  }
</script>

Don’t miss the official middleware docs to dive deeper!

# The “plugins” Folder

How do you register global components in a “normal” Vue app?

You add the following code to your main.js file:

import MyComponent from 'path/to/my-component'

Vue.component('my-component', MyComponent)

The same approach is used to register global directives or filters etc.

Where do you add that code in a Nuxt.js project though? You got no main.js file there!

The answer is: You create a plugin.

That sounds like a big thing. It sounds like you’re about to create a big package, an entire JavaScript library even.

It’s way simpler than that!

You simply add a file to the plugins folder - maybe plugins/global-components.js.

In that file, you import Vue (import Vue from 'vue') and you add the above code to register a global component/directive/…

Once that’s done, you just have to inform Nuxt.js about your newly created plugin. You do this in the nuxt.config.js file.

There, you either find or add a plugins property to the exported object. It should look like this:

module.exports = {
  plugins: ['~/plugins/vue-notifications'],
}

plugins holds an array of paths, pointing to your custom plugin files. The ~ works like the @ sign (which isn’t available in that file) and references the root folder.

And that’s it! Nuxt.js will now execute the code in that file (or all referenced files of course) whenever your app starts!

You can of course dive deeper by exploring the official docs on plugins.

# Other, Custom Folders

You learned about a lot of folders Nuxt.js is able to work with. Besides the pages folder, all folders were optional. But if you use them, you have to stick to the name Nuxt.js expects.

Besides these folders, you can of course add your own ones to organize your project code. You can add a mixins or filter folder to organize your mixins and filters. You can import the files from these folders into any of your other files.

For example, you can define filters in the filters folder and import them into some plugins/global-filters.js file to register the filters as global filters when your Nuxt app starts.

That is possible and something you have to keep in mind: You can add more folders and you can of course name these folders however you want!

# The “nuxt.config.js” File

A Nuxt.js app is mostly configured through folders and files. Some configuration can and has to be done in a JavaScript file though: The nuxt.config.js file which is created as part of every new Nuxt.js project.

In its leanest version, this file is pretty empty because Nuxt.js works pretty well out of the box. But you can dive into this file much deeper and configure every tiny bit of the Nuxt.js app exactly to your needs.

You can set global page transitions, extend the inferred routes, adjust the build configuration (Webpack!), configure the build mode (universal vs spa) and much, much more!

The official docs allow you to explore all the options you got.