<zeref.dev/>
All posts

Why this blog is just MDX files

When I decided to add a blog to this site, my first instinct was to evaluate tools. Payload, Contentful, some headless CMS with an admin panel. That instinct is worth examining, because it is the same instinct that over-engineers everything else.

Who is the editor?

A CMS earns its keep when non-technical people edit content. That is the whole pitch: a database, an admin UI, auth, roles, previews, so that someone who does not live in a code editor can publish safely.

The editor of this blog is me. I am a developer. I am already in an editor all day, and the site is a statically generated Next.js app in a git repo. For this setup:

  • Git is the CMS. Drafts are uncommitted files, publishing is a push, history is free.
  • The build is the pipeline. Every post is statically generated like the rest of the site.
  • The editor is the editor. No admin panel will beat the one I use for everything else.

The implementation

Each post is one .mdx file that exports its own metadata:

export const metadata = {
  title: 'Why this blog is just MDX files',
  description: '...',
  date: '2026-08-23',
  cover: '/blog/covers/[slug].png'
};

The index page reads the content folder, imports each post's metadata, and sorts by date. The post page dynamically imports the MDX and renders it through a small set of styled components. No frontmatter parser, no content layer library, no database. The whole thing is one config change and a handful of files.

The best code is the code never written. The second best is the code you can delete without anyone noticing.

If this blog ever needs tags, search, or an RSS feed, each of those is an afternoon of work on top of plain files. And if that need never comes, I will have spent zero time building and maintaining features nobody used.

The plumbing is settled, which leaves the hard part: having something worth writing down. That was the point of keeping the plumbing boring.