Next.js Markdown blog
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} />
</>
);
}
}