Next.js Markdown blog

13.11.20181 Min Read — In Tutorial, Web, React, Next.js

Next.js is a great React framework. It's easy to use and lightweight. I use it on my personal website (toukopeltomaa.com).

In this post I'm going to show how to make a simple blog using Markdown and Next.js.

1. Create folder for all Markdown files

Create a folder named posts root of your project. Create all of your posts as Markdown there

Example Markdown file in posts/example-post.md

---
title: Example post
date: 13-11-2018
writtenBy: Touko Peltomaa
---
## Example post

2. Add Webpack plugin raw-loader to next.config.js

We need raw-loader to load Markdown files

npm i -D raw-loader

next.config.js file

Create next.config.js to your project's root folder if you haven't already

module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.md$/,
use: 'raw-loader'
});
return config
}
}

3. Create home page at pages/index.js

Parse posts

We are going to parse posts with gray-matter library

gray-matter library will parse the YAML metadata. We can use the YAML data for SEO, written by and post dates.

npm i -S gray-matter

Gets posts from posts/* folder

import React from 'react'
import matter from 'gray-matter';
import Link from 'next/link';
export default class extends React.Component {
static async getInitialProps() {
// Get posts from folder
const posts = (ctx => {
const keys = ctx.keys();
const values = keys.map(ctx);
const data = keys.map((key, index) => {
// Create slug from filename
const slug = key.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.');
const value = values[index];
// Parse document
const document = matter(value);
return {
document,
slug
};
});
return data;
})(require.context('../posts', true, /\.md$/));
return {
posts
};
}
render() {
return (
<>
<h1>Posts</h1>
{this.props.posts.map(({ document: { data }, slug }) => (
<Link href={{ pathname: '/post', query: { id: slug } }} key={slug}>
<h2>{data.title}</h2>
</Link>
))}
</>
)
}
}

The getInitialProps function gets posts from posts folder and returns them in a usable format. We are going to use your filename as our post's slug or id

3. Create post page at pages/post.js

Get document name from querystring, require it and parse it.

Install React Markdown

To render Markdown we are going to use react-markdown

npm i -S react-markdown
import React from 'react'
import matter from 'gray-matter';
import ReactMarkdown from 'react-markdown';
export default class extends React.Component {
static async getInitialProps({ query }) {
const post = await import(`../posts/${query.id}.md`);
const document = matter(post.default);
return {
...document
};
}
render() {
return (
<>
<h1>{this.props.data.title}</h1>
<i>{`Written by ${this.props.data.writtenBy} | ${this.props.data.date}`}</i>
<ReactMarkdown source={this.props.content} />
</>
)
}
}