In the first part of this series, we learned How to set up a blog using Netlify CMS. In this part, we’ll see how to integrate the content with the NuxtJS frontend.

Setting up Vuex store to collect data

In your store directory create a file named index.js and add the following content to it.

export const state = () => ({
  blogPosts: []
});

export const mutations = {
  setBlogPosts(state, list) {
    state.blogPosts = list;
  }
};

export const actions = {
  async nuxtServerInit({ commit }) {
    let files = await require.context(
      "~/assets/content/blog/",
      false,
      /\.json$/
    );
    let blogPosts = files.keys().map(key => {
      let res = files(key);
      res.slug = key.slice(2, -5);
      return res;
    });
    await commit("setBlogPosts", blogPosts);
  }
};

Now we can use the content in our Vue files. To learn more about Vuex store in NuxtJS see this.

To use nuxtServerInit action your mode should be universal in nuxt.config.js

Getting data from Vuex store

In pages/ directory in index.vue file add the following content -

<template>
  <div>
    <h1>Blog Posts</h1>
    <div class="blogs">
      <ul class="blog" v-for="blog in blogPosts" :key="blog.slug">
        <li class="blog__title">
          <nuxt-link :to="`/blog/${blog.slug}`">
            <h2>{{ blog.title }}</h2>
          </nuxt-link>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  computed: {
    // Fetching all posts data
    blogPosts() {
      return this.$store.state.blogPosts;
    },
  },
};
</script>

Now if you go to your http://localhsot:3000/ you’ll see all the blog posts listed there.

Getting a single blog post

Use the following code to get the single blog post

export default {
  // Fetching Single BlogPost
  async asyncData({ params, payload }) {
    if (payload) return { blogPost: payload };
    else
      return {
        blogPost: await require(`~/assets/content/blog/${params.blog}.json`)
      };
  }
};

Now the blogPost variable is available in the template.

<div class="blog">
    <img v-bind:src="blogPost.thumbnail" class="blog__featured-img" />
    <h1 class="blog__title">{{blogPost.title}}</h1>
    <div class="blog__date">{{blogPost.date}}</div>
    <div class="blog__body" v-html="$md.render(blogPost.body)"></div>
  </div>

Since the body contains the markdown, we need to install a package to display the markdown content.

npm install @nuxtjs/markdownit

In your nuxt.config.js add the following line

...
modules: ["@nuxtjs/markdownit"],
...

Generating pages

To render the site as static, you need to add a generate property in your nuxt.config.js

generate: {
    routes: function() {
      const fs = require("fs");
      const path = require("path");
      return fs.readdirSync("./assets/content/blog").map(file => {
        return {
          route: `/blog/${path.parse(file).name}`, // Return the slug
          payload: require(`./assets/content/blog/${file}`)
        };
      });
    }
  },

I have also created a repository to get you started with the NuxtJS blog.

Reference - Netlify CMS Docs