How to setup dynamic routes in Nuxt.js

vstothard

Verity Stothard

Posted on May 1, 2019

How to setup dynamic routes in Nuxt.js

When working with dynamic pages in Nuxt, such as when we have a CMS with blog posts, we soon find that we need a way to generate routes for each post, e.g. www.veritystothard.com/blog/a-post/.

I came across this issue when building my own website using Contentful. My dynamic pages worked a treat on first load; the post slug passed in the <nuxt-link /> allowed me to pre-render the required post using the asyncData method, and a call to Contentful returned an entry of type blogPost with a slug matching that in the URL. However, when I refreshed the page, it was gone.

This issue occurred because I had not defined the routes I needed Nuxt to generate for my dynamic page in the config file, so when nuxt generate ran, no routes were created.

A quick fix for the issue is to simply add the route for each post to the routes array in the nuxt.config.js file,

    export default {
    ...
      generate: {
          routes: [
              '/blog/a-post',
              '/blog/another-one'
          ]
      }
    ...
    }

but that approach would soon become tedious and inefficient when adding new posts in the future.

A better approach is to generate an array of routes depending on your entries. For this example, I will be using entries of type blogPost pulled from Contentful, but the concept could apply to various CMS / data sources.

First, I set up my client and did a call to Contentful to return the slug of all entries with the type blogPost. I then formatted each slug to suit the folder structure of my website and pushed it to the routes array (e.g. the slug a-post became /blog/a-post).

    require('dotenv').config()

    const contentful = require('contentful')
    const config = {
      space: process.env.CONTENTFUL_SPACE_ID,
      accessToken: process.env.CONTENTFUL_ACCESS_TOKEN
    }
    const client = contentful.createClient(config)

    export default {
        generate: {
          routes: async function () {
            const entries = await client.getEntries({ content_type: "blogPost" });
            const routes = []
            entries.items.forEach(item => {
              routes.push(`blog/${item.fields.slug}`)
            })
            return routes
          }
       }
    }

To test my solution, I ran yarn generate and saw that a route for each of my pages and posts were logged in the console. I then deployed my changes to my Netlify project and saw that on page refresh, my content persisted 🙌

This post was originally published on veritystothard.com

💖 💪 🙅 🚩
vstothard
Verity Stothard

Posted on May 1, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related