Dynamic Routes on Nuxt.js
How to properly create dynamic routes using the generate command for building static websites on Nuxt.js.
Published on April 23, 2020

Wondering why Nuxt isn’t generating your blog posts after using the generate
command? you must specify the routes yourself! But fear not, it’s really simple.
TL; DR
// nuxt.config.js
import fs from 'fs'
import * as path from 'path'
const getPaths = () =>
fs
.readdirSync(path.resolve(__dirname, 'posts'))
.filter((filename) => path.extname(filename) === '.md')
.map((filename) => `/blog/${path.parse(filename).name}`)
export default {
generate: {
routes: getPaths()
}
}
Setup
First, make sure your folder structure looks like the code block below, it doesn’t have to be the same though. The _
prefix on a file name indicates a dynamic route.
pages/
--| index.vue
--| blog/
----| index.vue
----| _slug.vue
If everything checks out we are going to need a folder to host all of our markdown posts, so let’s create one at the root of our project. For the sake of this tutorial I’ll be using a generic name such as posts
, more on that later.
mkdir -p posts
Within pages/blog
edit the _slug.vue
page. Make sure the asyncData
function imports a post like the example below. The views (template
section) can be anything you want.
<!-- pages/blog/_slug.vue -->
<template>
<article>
<header>
<h1 v-text="title" />
<p v-text="description" />
</header>
</article>
</template>
<script>
export default {
async asyncData({ params }) {
// import a post based on the url params
// the `/blog/my-post` route will import `posts/my-post.md`
const post = await import(`~/posts/${params.slug}.md`)
return {
// this will only work if you are extracting
// front matter from the post using something
// like `frontmatter-markdown-loader`
// if that's not the case just return `post`
// and render the whole thing
title: post.attributes.title,
description: post.attributes.description
}
}
}
</script>
Note: Parsing markdown front matter is not in the scope of this article but you read about it here.
Create a new post under our previously created posts
folder.
# posts/my-post.md
---
title: My Title
description: My description.
---
...
If everything is setup, let’s get down to business.
The Solution
All we have to do is tell Nuxt to fetch our posts and map them to a url-like scheme so the generator knows what to render (and generate) alongside our static pages.
Add the following code to your Nuxt configuration file:
// nuxt.config.js
import fs from 'fs'
import * as path from 'path'
// our helper function
const getPaths = () =>
fs
// read all files in the `posts` folder
.readdirSync(path.resolve(__dirname, 'posts'))
// filter any `.md` file
.filter((filename) => path.extname(filename) === '.md')
// map to url, assuming your blog path is `/blog/`
.map((filename) => `/blog/${path.parse(filename).name}`)
export default {
// stripped
}
And finally, at the very bottom of the file, inside the export default
bracket, tell the generate
option to use our helper function.
// nuxt.config.js
export default {
generate: {
routes: getPaths()
}
}
You may now use the generate
command safely and without any worries.
Fin
That’s it, thanks for reading.