Joe Gilmore

6 min read

Markdown Blogs with Next JS

This website makes use of Markdown files to generate it's blog articles, NextJS then builds them into static HTML files at build time. This article explains how they work!

Markdown Blogs with Next JS

NextJS is a cool framework for ReactJS. It allows you to build sites using the familiar React framework, but instead of having a single page application that is poor for SEO it instead allows you to generate all pages as static endpoint .html files, once your user lands on that page it becomes your starting point to run the rest of your website as a React application so you get the best of both worlds! Yay!

Whats also great is that because NextJS can build your pages it can make use of things such as the fs filesystem so we can read .md markdown files at build-time and convert them into HTML files for our website.

Please note - these examples are using TypeScript

Plugins Required

In order to get this setup, we first have to install a few plugins: gray-matter, react-markdown & react-syntax-highlighter - once installed we can begin by first creating a file that reads our .md files:

import fs from 'fs'
import path from 'path';
const postsDirectory = path.join(process.cwd(),'markdown-blogs')
export function getBlogsFiles(){
    return fs.readdirSync(postsDirectory)
}

...This picks up all of blog files within our ./markdown-blogs folder, this uses the gray-matter plugin in order to pre-process our markdown files. So next lets take a look at a sample markdown file called: sample-file.md :

---
title: 'Sample Blog File'
date: '2022-01-01'
imageUrl : 'https://images.unsplash.com/photo-1533090161767-e6ffed986c88?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1738&q=80'
authorName: Joe Gilmore
excerpt: 'This is a very simple and basic markdown file used as an example!'
isFeatured: false
readingTime: 1 min
authorName: Joe Gilmore
authorURL: https://www.joemore.com/
authorImageURL: /images/avatars/account-avatar-profile-user-01-svgrepo-com-cropped.svg
---

# Heading 1

A simple paragraph goes here... and you basically just keep wiring content for your blog... You can **bold** text and *italicize* text and everything else you can think of with markdown!

...so next we create a function that parses this markdown file using gray-matter plugin to process the content and the metadata inside of the --- and closing --- hyphens:

import matter from 'gray-matter'
export function getBlogData( postIdentifier: any ) {
    const postSlug = postIdentifier.replace(/\.md$/,'') // removes file extension
    const filePath = path.join(postsDirectory, `${postSlug}.md`)
    const fileContent = fs.readFileSync(filePath,'utf-8')
    const { data, content } = matter(fileContent)
    const postData = { slug: postSlug , ...data, content, }
    return postData
}

With our blog articles all in this format we can then use a page to display them by mapping over our array of articles, and then finally to display the actual blog content we can use the react-markdown plugin to parse our Markdown and turn it into HTML for us. For an extremely basic output we can can simply do the following:

import ReactMarkdown from 'react-markdown'
export default function BlogContent( {BlogData} ) {
    return <>
        <h1>{BlogData.title}</h1>
        <ReactMarkdown>{BlogData.content}</ReactMarkdown>
    </h1>
}

However, if you want to take advantage of adding some nice styling to your blog article page, this is where making use of the react-syntax-highlighter comes into play, you essentially create a customRenderer object and pass this into your <ReactMarkdown> component like this:

import ReactMarkdown from 'react-markdown'
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter'
import atomDark from 'react-syntax-highlighter/dist/cjs/styles/prism/atom-dark'
import js from 'react-syntax-highlighter/dist/cjs/languages/prism/javascript'
const customRenderers = {
        code: ( {node, inline, children, className, ...props} : any ) => {
            const match = /language-(\w+)/.exec(className || '')
            return !inline && match ? (
            <SyntaxHighlighter 
                style={atomDark} 
                language={match && match[1] || ''} 
                children={children} {...props}>
            </SyntaxHighlighter>
            ) : (
                <code className="bg-red-100 text font-mono text-red-800 px-1 rounded-md"{...props}>
                {children}
                </code>
            )
        }
    }
export default function BlogContent( {BlogData} ) {
    return <>
        <h1>{BlogData.title}</h1>
        <ReactMarkdown components={customRenderers}>{BlogData.content}</ReactMarkdown>
    </h1>
}

In the example above we are using the SyntaxHighlighter to highlight our <pre><code></code></pre> and our singular <code></code> tags

Enjoy blogging in Markdown!!