Most developers building a personal site reach for Hugo, Astro, or a hosted platform. I built my own static site generator in Go. Not because the alternatives are bad — Hugo in particular is excellent — but because writing your own is a more interesting problem, and the result is something I understand completely.
Why custom
I've used Hugo before. It's fast, well-documented, and has a large theme ecosystem. But for a personal site I'm going to maintain indefinitely, I'd rather own a few hundred lines of Go I wrote than debug someone else's template system when something breaks.
There's also the honest answer: I'm actively learning Go, and building something real is how I learn. A static site generator is a well-scoped project with clear requirements, real output you can look at, and enough interesting problems (frontmatter parsing, template composition, RSS generation) to make it worth doing.
How it works
The generator lives in cmd/build/ and does five things:
- Walk
content/posts/,content/projects/, andcontent/pages/and parse each Markdown file - Extract YAML frontmatter (title, tags, description, draft status) using
gopkg.in/yaml.v3 - Render Markdown to HTML using goldmark with syntax highlighting via goldmark-highlighting and Chroma
- Apply
html/templatelayouts and write static HTML tooutput/ - Generate an RSS 2.0 feed at
/feed.xml
That's it. No incremental builds, no asset pipeline, no plugin system. The whole thing builds in under a second.
Content
Every post, project page, and static page is a Markdown file with YAML frontmatter:
---
title: "How This Site Is Built"
tags: ["go", "devops", "meta"]
draft: false
description: "A short description for the post list and meta tags."
---
Setting draft: true skips the file during the build. That's the entire content
management system.
Deployment
The site is hosted on an EC2 instance served by nginx. Deployment is handled by
Woodpecker CI — my self-hosted CI runner — on every
push to main. The pipeline builds the Go binary, runs the build, and rsync's the
output/ directory to the server. The whole deploy takes about 15 seconds.
Forgejo is the source of truth for the repository, mirrored to GitHub as a backup. A push to main is all it takes to ship a change — including new posts — so deploying is just part of my normal git workflow.
Design
The site uses Pico CSS as a baseline with custom CSS variables on top. Dark mode by default, light mode toggle persisted to localStorage. The color palette is zinc and cyan — dark backgrounds, cards that sit slightly above the page surface, and a cyan accent that shows up on links and active nav items.
No JavaScript frameworks. The only script on the page is the theme toggle, which is
about ten lines inlined in the <head> to prevent a flash of the wrong theme on load.
What's missing
No pagination yet — I'll add it when the post count warrants it. No search, no comments, no analytics. The RSS feed is there if you want to follow along without giving anything up.
The source for this site is on GitHub.