Home

Nuxt Content module, slug and articles

Using params.slug to fetch content

Create a articles folder inside pages

Create a _slug.vue file

The template is similar.

<template>
  <div>
    <nuxt-content :document="post" />
  </div>
</template>

Some changes in script, using params.slug:

export default {
  async asyncData ({ $content, params }) {
    const post = await $content('articles', params.slug).fetch()

    return { post }
  }
}

The first article I created was content/articles/nuxt-content-ssg.md.
To see it visit /articles/nuxt-content-ssg.

You should see the content you created.

A list of blog posts at /articles

We want to create a list of articles.

Create an index.vue file in pages/articles

No <nuxt-content/> this time…
The $content('articles').fetch() will return all the content of our articles that's too much for what we need.
If you want to see what's there you can display it inside a <pre>.

You can also use the /_content/articles route, some more Nuxt magic there…

<template>
  <div>
    <pre>
        {{ posts }}
    </pre>
  </div>
</template>

<script>
export default {
  async asyncData ({ $content }) {
    const posts = await $content('articles').fetch()

    return { posts }
  }
}
</script>

The Nuxt Content Module let us filter only the data we need.

export default {
  async asyncData ({ $content }) {
    const posts = await $content('articles')
      .only(['path', 'title', 'createdAt', 'updatedAt'])
      .fetch()

    return { posts }
  }
}

createdAt and updatedAt are added directly by Nuxt Content.

This data should be enough.
To display the data on our page, we'll loop over the posts.

<ul class="PostsList">
  <li v-for="post in posts" :key="post.slug" class="PostsList-item">
    <nuxt-link class="MainLink" :to="post.path">
      {{ post.title }} &mdash; <small>{{ post.createdAt.split('T')[0] }}</small>
    </nuxt-link>
  </li>
</ul>

You can see the result on the articles page

Prev and Next links at the end of each article

I'm writing a step by step guide, it would be cool if you can follow the steps without going to the list page, so let's add it in our articles/_slug.vue component.

Nuxt Content Module has the surround helper to fetch the previous and next article. You can read more about it on the Nuxt Content Module documentation site

import PrevNext from '~/components/PrevNext'

export default {
  components: {
    PrevNext
  },
  async asyncData ({ $content, params }) {
    const post = await $content('articles', params.slug).fetch()
    const surround = await $content('articles')
      .sortBy('createdAt', 'asc')
      .only(['title', 'path', 'createdAt'])
      .surround(post.slug).fetch()

    return { post, surround }
  }
}

As you can see, I created a component, PrevNext.vue.
This component will be added after the content of each article. The template is now :

<template>
  <div>
    <nuxt-content :document="post" />

    <PrevNext :surround="surround" />
  </div>
</template>

The component is quite simple :
It takes a surround prop, we check that the prev or next links are there to display the link.

<template>
  <div class="PrevNext">
    <nuxt-link v-if="surround[0]" :to="surround[0].path" class="PrevNext-prev">
      <small>[Prev]</small><br>{{ surround[0].title }}
    </nuxt-link>
    <nuxt-link v-if="surround[1]" :to="surround[1].path" class="PrevNext-next">
      <small>[Next]</small><br>{{ surround[1].title }}
    </nuxt-link>
  </div>
</template>

<script>
export default {
  props: {
    surround: {
      type: Array,
      default () { return [] }
    }
  }
}
</script>

We now have a website with an homepage, a blog with a list of articles and links to go to the previous or next article.

Let's add Forestry (a git-based headless CMS), to edit the content of our Nuxt site.