ryu.com
Cover: Three weekends to build my blog a static generator
Code

Three weekends to build my blog a static generator

Jul 11, 2026 · ≈ 13 min read

Here's how it happened: my blog needed rebuilding. After the GCP ban I decided never to depend on a backend again. But hand-writing HTML to maintain dozens of posts obviously wasn't realistic. I needed a tool.

The existing options were all too heavy — Hugo, Jekyll, Astro, Next.js. They're good tools, but I didn't want to pull in 200MB of node_modules for a blog. I needed exactly three things: turn Markdown into HTML, wrap it in a template, generate RSS.

So over three weekends, I wrote a Node script in under 200 lines.

Weekend one: figuring out what NOT to build

The problem with most tools isn't too few features — it's too many. I spent the first weekend writing a "not needed" list:

This process of subtraction mattered more than writing code. It forced me to see what a blog actually needs: content + typography + links. Everything else is noise.

Weekend two: writing the code

The core logic was simple:

const fs = require('fs');
const path = require('path');
const { marked } = require('marked');

// Read all Markdown files
const posts = fs.readdirSync('content')
  .filter(f => f.endsWith('.md'))
  .map(f => parsePost(f))
  .sort((a, b) => b.date - a.date);

// Generate each post's HTML
for (const post of posts) {
  const html = applyTemplate(post);
  fs.writeFileSync(`dist/${post.slug}.html`, html);
}

// Generate the index page
const indexHTML = applyIndexTemplate(posts);
fs.writeFileSync('dist/index.html', indexHTML);

// Generate RSS
const rss = generateRSS(posts);
fs.writeFileSync('dist/rss.xml', rss);

The real code was a bit longer — frontmatter parsing, URL normalization, relative paths, syntax highlighting. But the core idea was those three steps: read, transform, output.

Weekend three: deleting it all and rewriting

After weekend two, I tried importing 20 old posts. Several problems appeared:

On the third weekend I deleted the whole script and rewrote it. Simpler this time — I gave up on automatic Markdown conversion and hand-wrote the HTML instead. It sounds like a step backwards, but in practice:

In the end this "static generator" degraded into a 50-line script that does exactly one thing: scan the HTML files under posts/, extract titles and dates, and generate the list on the homepage.

Less is actually more

This experience made me rethink what "tools" mean. The best tool isn't the one with the most features — it's the one that's just enough. For a personal blog, a text editor and an HTML file are the best CMS there is.

If you want to start blogging too, my advice: write first, think about tools later. Get the content out, put it in an HTML file, upload it anywhere that hosts static files. When hand-maintaining becomes painful, then consider automation. But most of the time, the pain of maintaining things by hand is far smaller than the pain of learning a complex framework.


This site's source can be found on GitHub. No build step — clone it and it just runs.

Keep reading