This blog is built with MDX

MDX was created by members of the Next.js team so it is relatively to combine the two for a basic blog like this one.

Why MDX?#

As a developer, I am comfortable in a text editor and know enough Markdown syntax to write freely. I expect most of the writing I do here will be text and media, which is easy in MDX.

But I also need some level of control for the cases that don't work as well in pure Markdown. Even my first post on the color palette of this site had me wanting a React component that could render our the palette's colors and hex values.

import PalettePreviews from '../components/PalettePreviews';

# How I chose the color palette for this site

Choosing a color palette for a web site is...

<PalettePreviews />

Why Next.js?#

I have been working with Next.js for over 2 years now. It can be a challenging framework at times but it also provides flexibility so if you get over the learning curve, you can do just about anything. This is a side project, and with side projects I usually take the opportunity to try something new. In the past, the "new thing" would slow me down so much that I would lose interest in the project entirely. In the case of this blog, I had enough experience with Next.js and MDX that it only took me a few hours to get it up and running. I still was able to introduce 1 new thing, TypeScript, which I'll need to save for another post.

Metadata#

One annoying thing I found with the Next.js + MDX combo was attaching metadata to each post. I found this Building a static blog site with Markdown and Next.js post that seemed to have what I wanted:

export const meta = {
  published: true,
  publishedAt: '2019-01-15',
  title: 'This is my very first blog post',
  summary:
    'I am learning how to build a blog using Markdown in a static web page build on top of Next.js'
};

But then I looked at the code required to power that and didn't really care for it.

I found this NextJS Blog with Markdown files example that used frontmatter to capture metadata.

---
title: "Hello World"
date: "2020-01-07"
---

And it turns out there is a remark-frontmatter plugin that can help with this and Next.js's MDX plugin makes it easy to add remark and rehype plugins (yep, it's plugins all the way down).

const frontmatter = require('remark-frontmatter');
const rehypePrism = require('@mapbox/rehype-prism');

const withMDX = require('@next/mdx')({
  extension: /\.mdx?$/,
  options: {
    remarkPlugins: [frontmatter],
    rehypePlugins: [rehypePrism],
  },
});
module.exports = withMDX({
  pageExtensions: ['js', 'jsx', 'mdx', 'tsx'],
});

Using metadata on the index page#

With frontmatter in place, I could then pull the metadata into the index page via Next.js's getStaticProps. This runs at build time.

export async function getStaticProps(context) {
  const pageMeta: Array<any> = glob
    .sync('./pages/**/*.mdx')
    .map((file) => {
      const m = matter.read(file);
      if (m.data.title) {
        return {
          ...m.data,
          path: file.replace('./pages', '').replace('.mdx', ''),
        };
      }
    })
    .filter((m) => !!m);

  return { props: { pageMeta } };
}

A newsletter for curious developers

Join me on the fantastic journey of software development. JavaScript, CSS, HTML, React, Next.js, Flutter, GraphQL, Fauna.