After over a year of procrastination, I finally finished rewriting my blog from scratch. Here is how it all happened.

(I have many to write and expects this to be a series. This is part 1.)

Why the rewrite?

I built the original blog back in 2018 using Hexo, a static site generator written in JavaScript. Hexo represented less of a deliberate choice than an absence thereof: it was popular—tutorials were everywhere—and I wanted to set up my blog ASAP. Hexo served that purpose well. It is also hackable enough to accommodate some of my customization needs, so it stayed for six years.

If it works, don’t touch it.

They say that’s the first rule of engineering. So why bother the rewrite?

  1. It’s cool. Who doesn’t want to design his personal website from scratch if he got the time and skill? Breaking free of existing frameworks by others gives me more room in making things that represent and express myself—a big reason I built my blog in the first place.
  2. It’s a good learning experience. Rewriting my blog would expose me to full-stack web development and a bit of visual design. Both were out of my comfort zone but I believe they are good skills to have. As opposed to going through tutorials and textbooks, I much prefer having a project like this where I can practice these skills hands-on.
  3. Hexo is not good enough. Hexo itself is small, but the theme I use was a kitchen sink of features. Like any other all-in-one libraries, it attracted me as a beginner back then because it looks pretty and everything works out of the box. But as I wanted more features, I found myself constantly drilling holes into leaky abstractions and puzzling design decisions. I’ve had enough hacks.

So by late 2022, I was fully motivated to the rewrite and prioritized it over writing new posts. The rest is to actually get it done.

Interesting Things to Try

Beyond the obvious objective of more control, I wanted take the opportunity of this rewrite to try many things I had struggled to implement on the old blog:

  1. CDN-friendly server: Mostly a matter of personal preference. Static sites are great—but I’ve tried them already—and having a server would made features like comments easier to implement and leaves the most flexibility for the future. I don’t expect my blogs to have many visitors, but my single-core 1G-memory VPS isn’t too powerful either, so I planned to add Cloudflare in front of it to reduce and balance the load. Going server-less is another option, but I fear there’s too many moving parts and there are too much vendor lock-in in the server-less landscape at the moment.
  2. Better LightHouse score: That’s probably a blunt way to phrase it. Alternatively: I want to improve user experience on my blog! Snappier, more readable, more accessible. LightHouse score is good metric of all these and is very easy to measure. Busy and lazy as I am, it will be the measure I go to. The old Hexo blog had a score of ~80. The rewrite must improve this.
  3. Minimalist design: My euphemism for “I am not good enough to do fancy graphics and too lazy to write many lines of CSS.” Besides, from an engineering perspective, premature generalization is just as bad as premature optimization. I wanted to scope this rewrite as a rewrite of my blog, not Hexo the blog engine. Every line of the code should be the minimum that does the job cleanly and nothing else. Future usually don’t go along how you future-proofed your code, so why sort things to config files so fast?

Over the course of the rewrite I developed a few other stretch goals, but these should be all. Now let’s zoom into the development process.

How it’s Done: Index to Other Posts

When I started writing this post, I thought three posts would be plenty for this series and I would expand the first part of the dev process right here. However, as I wrote, I found that much of my experience—and thoughts—of how my blog became the way it is more self-contained, has potentially broader scopes, and hence deserve to be separate posts1. So I am in an awkward position now: 700 words into this post and I have nothing to write!

So I think it’s best to use this space as an index for you and a planner for me. Here it is:

  1. The Language Decision: See Rewriting blog is so much fun (2): Exit JavaScript; Enter Go (and passes Rust), where I discussed how I ditched JavaScript and chose to write the new server end of my blog in Go.
  2. Using Go, HTMX, and Docker (TODO): The post above turned out to be rather high-level, so in this post I’ll dive into the details of how I set up my development and deploy environment to achieve good DX and easy deployment.
  3. Typography (TODO): One stretch goal I developed in rewriting the blog—and one I believe has been largely achieved—is to improve the typography of my blog. I chose and bought a professional font I like for the first time in my life; I worked my way to find a matching Chinese font; I overcame challenges to serve these fonts efficiently. It’s been a cool experience I want to dedicate a separate post to.
  4. (TODO): The rewrite is not fully complete yet so far, so there may be new contents I want to cover. Leaving this placeholder for now.

Stay tuned.


  1. Another practical reason to split all these discussions into separate posts is SEO. Apparently, blog posts of 1000-2500 words are optimal for search engine indexing.↩︎