Andy Bedinger

Decisions in Setting Up a Developer's Personal Blog Site

12/23/2021

Setting up a personal blog site can be a daunting task for a developer. By nature, we build rather than buy. And we're particular about what we want. Because of this, while others would happily pick a commercial service and immediately get started writing prose, we face tough decisions and spend hours writing custom code before we ever get to writing our first article. This post describes how the process went for me, and some of the challenges I faced along the way.

First, here is a list of the technologies that I chose for this site. If you're doing something similar, reading on may save you some time.

  • React
  • Next.js
  • Markdown
  • MDX
  • Tailwind CSS
  • highlight.js

Early Decisions to Make

What to Build With

The build versus buy decision is already made. It's not as easy to decide what to build with, however. Using JavaScript for personal blog sites is quite popular, and has obvious appeal to a JavaScript developer. However, as a HashiCorp developer wisely wrote:

If you are trying to build a blog for personal or small business use, consider just using normal HTML and CSS. You definitely do not need to be using a heavy full-stack JavaScript framework to make a simple blog.

While that is true, there are advantages to using JavaScript. We like making things dynamic and keeping things DRY. We also enjoy learning and sharpening our skills. So, decision made: JavaScript.

How Much to Build

The question of how much to build can be rephrased as: how much do you want to learn? Unless you're a developer who focuses on building personal blog sites, you are facing a learning curve.

Deciding what to learn is, in part, a function of the likelihood you will ever use that knowledge again and how long it will be before your knowledge becomes obsolete.

There are popular JavaScript-based static site generators that do the heavy lifting for you. Gatsby is a popular example. Static site generators come with some overhead, though. You have to learn how to use them.

Then there are appealing personal blog sites made by other developers, who explain how they made their sites by bringing together a collection of libraries and some CSS. It looks slightly challenging and interesting. This is our siren call. We will do it 'not because it is easy, but because it is hard.'

JavaScript Decisions

JavaScript Library

As shown above, I chose React for the JavaScript library. In my case, I've used Vue.js and am using React now, and have not done anything with Bootstrap. React is popular and likely to be around for a while.

JavaScript Framework

I opted for Next.js, as it can be used for static generation as well as server-side rendering. While this site is not rendered server-side, that versatility makes it more likely I will wind up using Next.js again. That makes it worth it to learn.

Starter Template or New App Decision

Having decided on React and Next.js, the next decision is to create a blank React app, or use a starter template. Next.js offers a variety of starter templates. Some of them are even for personal blog sites.

The "blog" sample app is simple and is made for portfolio/blog sites, which seems ideal. It uses a Next static site generator called Nextra, which renders Markdown as HTML. However, Nextra's syntax highlighting is currently broken, and that is a show stopper. The other blog-related sample apps looked like overkill for my use case. npx create-react-app, here we come.

Content Format Decisions

Markdown

Markdown is popular, easy to use, and simplifies formatting. Since it is supported by many code editors, you can quickly view the rendered HTML as you write. All articles for this site will be written in Markdown. They will need to be converted to HTML, of course, for use on the site.

Front Matter

Metadata about files written in Markdown can be stored in YAML format in an area at the top of the file. This is referred to as front matter. For a site made up of articles, the metadata could contain a field for title, description, date and author. Then, by parsing the front matter in a group of files, a dynamic list of articles can be generated.

MDX

Markdown conversion can be performed by MDX, a language that is compiled to JavaScript. One nice thing about MDX is that you can put JavaScript in with your Markdown. For example, you could embed a React component in your Markdown. I don't need to do this, at the moment, but I definitely like having the option. The Next.js site has a nice blog post that addresses MDX.

MDX Plugins

Just choosing to use MDX, however, is not enough. There are multiple ways to use it. The recommended approach is to use @next/mdx and @mdx-js/loader to source MDX data from local files and render it as HTML.

Using YAML front matter presents a problem, though: @mds-js/mdx doesn't understand it. It just shows up in the HTML content. However, there is a remark plugin called remark-frontmatter which is supposed to address this problem. It doesn't, though. After struggling for hours with CommonJS vs ESM issues to even get the plugin loaded, I could not discern that it did anything at all.

Eventually, I opted to use next-mdx-remote, by HashiCorp. It doesn't try to render the YAML front matter as HTML.

MDX Implementation

It is possible to use MDX with file-system based routing, so that all *.mdx files in the pages/ directory are accessible from the browser without the .mdx extension. In my case, however, I wanted to apply a common layout to all of my articles. With file-system based routing, it would be necessary to embed the layout in every article, and I did not want to do that.

Instead, I opted to use dynamic routing. I have a file at pages/blog/[post].js which is called when a file matching pages/blog/*.mdx is loaded. Here is the part of the JavaScript file which renders the MDX content inside my Layout component:

  return (
    <Layout pageTitle={frontmatter.title}>
      <div className="w-full">
        <article className="prose max-w-none">
          <h1>{frontmatter.title}</h1>
          <p className="italic">{frontmatter.date}</p>
          <MDXRemote {...mdxSource}/>
        </article>
      </div>
    </Layout>

CSS Framework Decision

After you have made some of the bigger decisions, subsequent decisions become easier, partly because there are less practical options. The choice of CSS framework was not difficult to make after having chosen Next.js and Markdown. Tailwind CSS has a plugin called typography which automatically styles HTML elements inside a component containing Markdown.

Another popular option for CSS is Bootstrap. This blog post by LogRocket helped me make the decision. Bootstrap is, in part, a JavaScript framework. I've already picked Next.js as my framework. I could likely use Bootstrap only for CSS, but using something purpose-built is more appealing than using something all-encompassing.

Syntax Highlighting Decisions

A blog with articles about software development is going to have code samples. And code samples only look good with proper syntax highlighting. Code Hike looked interesting and works with MDX v2. It's intended to be used as a remark plugin. Like remark-frontmatter, however, it doesn't work. In fact, I found it returns different errors based on the Markdown content passed in to it. Since Code Hike is (at the time of writing) only in preview, and MDX v2 itself is new, this seems both expected and a bad combination.

I looked into using a remark plugin for shiki, but was unable to tell which was official. And, lack of success with any remark plugin for MDX limited the amount of time I was willing to spend on this approach.

Highlight.js seems to be popular and has a large number of themes. There is a rehype (not remark) plugin for highlight.js, and it actually works.

References

This article influenced many of my decisions. I made nearly all of the same technology decisions outlined in it, deviating mainly in the use of MDX and next-mdx-remote.

The JetBrains post on setting up a blog with Next.js and MDX helped me implementing MDX - far more than the Next.js site did.