← All articles

Field record

Next.jsEngineeringWorkflow

Why I moved my blog to build-time content

A personal blog does not need a server on every page view

Moving from Md to MDX and Next.js

I built BootFort.dev from a simple Node.js server template that reads Markdown files and renders them for each request. I got it running quickly—in a couple of minutes. It was simple and it worked, but the next question was obvious:

Why should a page that never changes be computed every time someone opens it?

Original setup

I needed a quick start. Otherwise, I would try to perfect this simple blog and never release it. In the end, I had been thinking about how to build it perfectly for half a year. So I used a template listed directly on the Vercel website, wrote an article, prompted an AI to build a design, and I was good to go.

And how was the user request flow?

Request → Node/Vercel function → read Markdown → render HTML → response

The benefits were clear:

  • no database
  • minimal abstractions
  • immediate content updates
  • easy authoring

Was request-time rendering necessary?

The posts are stored in Markdown files and merged through Git. Changes only happen when I merge a merge request (MR) into the main branch. There is no dashboard, admin panel, or page-related data such as comments, likes, or statistics. A more suitable approach is:

Write the blog post in MDX file -> Merge the MR -> build page once -> serve static HTML globally

What changed in the Next.js migration

  • Posts moved from publicly available Markdown files to a specific folder
  • The article metadata comes from the front matter
      ---
      title: Hi, World!
      ---
    
  • The build discovers every article and generates /blog/:slug
  • The home page and /blog listing are generated from the same content source.
  • Vercel serves the pre-rendered HTML and assets from the edge when requested.

Benefits that matter for a personal blog

  • Predictable performance - HTML already exists when a visitor requests it
  • Lower operational surface area - no server handler is needed to serve the request
  • Better content boundaries - source MDX is not exposed from /public.
  • Build-time validation - invalid required front matter is caught during the build
  • Easy hosting - static pages work well on Vercel and are easy to move later

What static generation does not solve

Somebody would say that a blog is not a blog without discussion. Maybe. Static generation cannot solve comment sections, authenticated areas, or reader-specific features that may need server functions later. Static generation is not "no backend ever"; it is choosing not to create one for content that does not need one.

One tradeoff is still present: publishing becomes a build.

A typo fix or every new article requires a new deployment instead of signing in to an admin console and updating an article in a database row. But for me, right now, it is totally acceptable—Git gives me review history, I can progress quickly, and I can focus on producing content instead of building a system around it.

Is this the best universal setup?

No, static generation is not universal. It is the right choice for this version of the blog: content changes through Git, pages are public, and each deployment can produce the complete site once. If the blog needs comments, accounts, or personalized content, I can introduce dynamic features where they are useful—without making every article request dynamic today.

The goal of a software engineer is not to find a universal solution, but to find the best solution for the situation at hand today while keeping a clear direction for future changes.