Skip to content

Touko's blog

Next.js Markdown blog

1 min read

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

1---
2title: Example post
3date: 13-11-2018
4writtenBy: Touko Peltomaa
5---
6## Example post

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

We need raw-loader to load Markdown files

1npm i -D raw-loader

next.config.js file

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

1module.exports = {
2 webpack: (config) => {
3 config.module.rules.push({
4 test: /\.md$/,
5 use: 'raw-loader'
6 });
7
8 return config
9 }
10}

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.

1npm i -S gray-matter

Gets posts from posts/* folder

1import React from 'react'
2import matter from 'gray-matter';
3import Link from 'next/link';
4
5export default class extends React.Component {
6 static async getInitialProps() {
7 // Get posts from folder
8 const posts = (ctx => {
9 const keys = ctx.keys();
10 const values = keys.map(ctx);
11
12 const data = keys.map((key, index) => {
13 // Create slug from filename
14 const slug = key.replace(/^.*[\\\/]/, '').split('.').slice(0, -1).join('.');
15 const value = values[index];
16
17 // Parse document
18 const document = matter(value);
19
20 return {
21 document,
22 slug
23 };
24 });
25
26 return data;
27 })(require.context('../posts', true, /\.md$/));
28
29 return {
30 posts
31 };
32 }
33
34 render() {
35 return (
36 <>
37 <h1>Posts</h1>
38 {this.props.posts.map(({ document: { data }, slug }) => (
39 <Link href={{ pathname: '/post', query: { id: slug } }} key={slug}>
40 <h2>{data.title}</h2>
41 </Link>
42 ))}
43 </>
44 )
45 }
46}

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

1npm i -S react-markdown
1import React from 'react'
2import matter from 'gray-matter';
3import ReactMarkdown from 'react-markdown';
4
5export default class extends React.Component {
6 static async getInitialProps({ query }) {
7 const post = await import(`../posts/${query.id}.md`);
8 const document = matter(post.default);
9
10 return {
11 ...document
12 };
13 }
14
15 render() {
16 return (
17 <>
18 <h1>{this.props.data.title}</h1>
19 <i>{`Written by ${this.props.data.writtenBy} | ${this.props.data.date}`}</i>
20 <ReactMarkdown source={this.props.content} />
21 </>
22 )
23 }
24}