D

Colophon

At this point, it’s almost inevitable that I’ll get bored and completely rebuild my personal site for no reason other than because I can.

Frankly, this whole site is overengineered to hell. I don’t care. Indulging in new technologies is a vice I refuse to give up.

Typography

Body copy is set with Galaxie Copernicus by Village. Copernicus was designed to be a body font, and it does that job very well. I love how light and playful the characters are.

Headers and other sans copy are Untitled Sans by the Klim Foundry. The monospace font used in code blocks is JetBrains Mono, an open-source typeface I also use in VS Code and terminal.

Technologies

This site is a Next.js application.

I’ve used Next.js since the previous iteration of my site in 2020. It’s a static site builder that takes care of shit like server-side rendering, image loading, and routing. They also have a silly amount of starter templates, which helps when you don’t know how to do anything.

The site is deployed on Vercel. I chose it back in 2020 because I figured the creators of Next.js would know a little bit about deploying Next.js, but honestly — Vercel is just so much fun to use.

Styling is handled by TailwindCSS, a utility-first CSS framework. I considered styled-components, but Tailwind utilities make building so much faster.

For example: I don’t want to handle dark mode on my own. With Tailwind, I just use dark: to support a dark variant of a component.

The most critical part of this whole build is MDX.

I love MDX

I wrote a bit about MDX in my previous site. Since that post was written, I’ve learnt a bunch of new and odd ways to soup up MDX even more.

When you use Markdown on a web app, the markdown is compiled into HTML. Asterisks become <strong>, lists become ul, and so on. That’s great, but it means you’re restricted to that set of HTML elements.

MDX lets you include your own elements as React components.

import {Chart} from './snowfall.js'
export const year = 2018
 
# Last year’s snowfall
In {year}, the snowfall was above average.
 
<Chart year={year} color="#fcb32c" />

You can create your own set of primitives and add them to content like I did with the sidenotes componentSidenotes look like this!, or build one-off components to support an article.

Running MDX on Next.js

As I write this, there’s four (4!!) ways to use MDX with Next.js.

  1. The official way is @next/mdx
  2. Hashicorp’s next-mdx-enhanced
  3. Hashicorp’s next-mdx-remote
  4. Kent C. Dodd’s mdx-bundler

next-mdx-enhanced now recommends using next-mdx-remote instead (though a lot of people are still on -enhanced).

I use mdx-bundler. Partially because it can bundle MDX dependencies, meaning it supports one-off component imports, but mostly because it was the only one I found good tutorials for.

Post metadata

I use frontmatter. This is what this blog post looks like.

---
title: How I built this site
description: An experiment with Next.js, Tailwind, and Vercel 
excerpt: The original version of my website was built with Webflow over New Year's 2019 (or even earlier). Now that we're moving into 2021, I figured it was time for a refresh. 
date: '2022-09-05'
slug: 'how-i-built-this-site'
isFeatured: true
image: images/blog/how-i-built-this-site/website-ss.png
---
Content!

The old site used const to define metadata. It was really annoying. YAML frontmatter is superior and easier on the eyes.

Code snippets

Of course I was gonna spend 20% of my time making code snippets look pretty.

Tailwind handles code block styling for me with prose, which is nice because hand-making a code block component sounds like hell.

Under the hood, I use Shiki via rehype-pretty-code for syntax highlightingThere’s also a really interesting Shiki + Twoslash implementation for self-contained code samples. If I ever wanted to create a code playground, I’d use Twoslash.. I like Shiki because it supports any VS Code theme, which makes it much easier to style than Prism.

Shiki also uses VS Code’s syntax highlighting engine instead of Prism’s regex-based highlighting. I’ve found it more accurate.

Image structure

Next.js requires all images to be in the /public folder. This is fine for images used on static pages, but I don’t like the messiness when it comes to images used within blog posts.

This is the structure Next.js expects:

- public/
   - images/
        - image.jpg
        - blogHero.jpg
        - avatar.jpg
- scripts/
- styles/

Very messy once you have >10 images. Instead, I wanted to store images next to the Markdown file. Like so:

- posts/
    - how-i-built-this-site/
        - index.mdx
        - website-ss.png
    - on-internationalization/
        - index.mdx
        - featureImage.jpg

There’s a hacky way of working around this, but I ended up using CodeConcisely’s method. This script copies the images from the post folder into /public and clears existing images at build.