DEV Community

Michael Hoffmann
Michael Hoffmann

Posted on • Originally published at mokkapps.de on

Create a Blog With Nuxt Content v2

I prefer simple Markdown files as the content source for my blog posts. In this article, I want to show you how can set up a simple blog using Nuxt Content v2.

Nuxt Content v2

Nuxt Content v2 is a Nuxt 3 module that reads local files from the /content directory in your project. It supports .md, .yml, .csv and .json files. Additionally, it’s possible to use Vue components in Markdown with the MDC Syntax.

Setup Nuxt App

First, let’s start a new Nuxt Content project with:

npx nuxi init nuxt-demo-blog -t content
Enter fullscreen mode Exit fullscreen mode

Then we need to install the dependencies in the nuxt-demo-blog folder:

yarn install
Enter fullscreen mode Exit fullscreen mode

Now we can start the Nuxt content app in development mode:

yarn dev
Enter fullscreen mode Exit fullscreen mode

A browser window should automatically open for http://localhost:3000. Alternatively, you can start playing with Nuxt Content in your browser using StackBlitz or CodeSandbox.

The following StackBlitz sandbox demonstrates the simple blog application we create in this article:

Blog Content Structure

Our demo blog will have this structure inside the /content directory:

├── blog
│ ├── _index.md
│ ├── a-great-article
│ └── cover.jpg
│ │ └── index.md
│ └── another-great-article
│ └── cover.jpg
│ └── index.md
Enter fullscreen mode Exit fullscreen mode

blog/_index.md is a Partial content that will show a list of all available blog posts.

Each blog post has its directory, including an index.md and a cover.jpg file.

The index.md files include Front-matter at the top of the file to provide meta-data to pages, like title, date, and the cover image URL:

---
title: A Great Article
date: 2018-05-11
cover: /content/blog/a-great-article/cover.jpg
---

This is a great article body!
Enter fullscreen mode Exit fullscreen mode

Simple Navigation

First, we need simple navigation in our application to be able to navigate to our blog page.

Let’s start by adding a default layout in layouts:

<template>
  <div>
    <nav>
      <NuxtLink to="/" class="link">Home</NuxtLink>
      <NuxtLink to="/blog" class="link">Blog</NuxtLink>
    </nav>
    <main>
      <slot />
    </main>
  </div>
</template>

<style>
.link {
  margin-right: 1rem;
}
</style>
Enter fullscreen mode Exit fullscreen mode

In our app.vue we need to wrap the NuxtPage component with the NuxtLayout component:

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Finally, we create a index.vue in pages directory:

<template>
  <h1>Home</h1>
</template>
Enter fullscreen mode Exit fullscreen mode

Home Page
Home Page

Blog List

Let’s look at how we can implement a list of all available blog posts.

First, we need to create a BlogPosts.vue Vue component in components/content/ that queries and renders all available blog posts:

<template>
  <h1>Blog</h1>
  <ul>
    <li v-for="{ _path: slug, title } in blogPosts" :key="slug">
      <NuxtLink :to="slug">{{ title }}</NuxtLink>
    </li>
  </ul>
</template>

<script setup lang="ts">
const blogPosts = await queryContent('/blog')
  .sort({ date: -1 }) // show latest articles first
  .where({ _partial: false }) // exclude the Partial files
  .find();
</script>
Enter fullscreen mode Exit fullscreen mode

We use the queryContent function from Nuxt to query a list of our blog posts.

Now we can reference this Vue component inside our content/blog/_index.md file:

---
title: Blog
---

::blog-posts
Enter fullscreen mode Exit fullscreen mode

We can use any component in the components/content/ directory or any component made available globally in your application in Markdown files.

If we now click on the “Blog” navigation link in our application, we can see a list of all available blog posts:

Blog Post List
Blog Post List

I reported a Nuxt content bug that you need to reload some routes; otherwise, their content is not visible.

Blog Post Page

Finally, we need to create a dynamic route for the blog posts. Thus, we create a [...slug].vue file in pages/blog:

<template>
  <ContentDoc
    :path="$route.params.slug ? `/blog/${$route.params.slug[0]}` : '/blog'"
  >
    <template #not-found>
      <h2>Blog slug ({{ $route.params.slug }}) not found</h2>
    </template>
  </ContentDoc>
</template>
Enter fullscreen mode Exit fullscreen mode

We use the current slug in the route parameters ($route.params.slug) to determine whether we want to render the blog post list or an individual blog post.

We can now see the content of the corresponding blog post:

Blog Post
Blog Post

Conclusion

It’s effortless to create a Markdown file-based blog using Nuxt Content v2. This article demonstrates the basic steps to set up such a blog.

You can expect more Nuxt 3 posts in the following months as I plan to blog about interesting topics that I discover while rewriting my portfolio website.

If you liked this article, follow me on Twitter to get notified about new blog posts and more content from me.

Alternatively (or additionally), you can also subscribe to my newsletter.

Top comments (0)