Building a CMS in Go, take one
Building a CMS in Go, take one
Two years ago, fresh out of a bachelor's in cyber security, I started pynezz_com: a content
management system and static site generator, written from scratch in Go, because reinventing the
wheel is a good way to actually learn how the wheel works.
The plan
The requirements I wrote down at the time still hold up:
- Markdown in, HTML out - my notes already lived in Obsidian-flavored markdown, so the framework had to speak that dialect.
- Authentication that keeps randoms off the internet from posting to my site, built myself rather than bolted on.
- A CLI to drive the whole thing, ideally with zero build step for a new page.
- A web server doing routing, auth, and server-side rendering, with nothing embarrassing left over from 2008.
What got built
Quite a lot, actually: an Echo server, templ-based templating, a GORM/SQLite-backed content
store, a markdown parser with a custom callout syntax modeled on Obsidian's >[!type] blockquotes,
JWT sessions, argon2 password hashing, and - further than I expected to get - a working WebAuthn
passkey registration/login flow.
What stayed open
One section of the project notes was titled, verbatim, "Implementing authentication - undecided":
- public key cryptography is probably the safest
- password based auth with argon2 hashing and sqlite and JWTs is probably easiest due to familiarity with those technologies in particular
- protocols such as SRP would be the most interesting to implement, but sadly I have not much experience with PAKE protocols
I shipped password auth and half of WebAuthn, and never actually closed that question out. The
project stalled before the CMS side (SQLite-backed posts, tag counts, a /tags/:tag route) saw
real content past two markdown test files.
Starting over
This site is the second attempt, and it drops almost everything from the first except the
questions it was trying to answer. No Echo, no templ, no GORM - just net/http, html/template,
and content that's files on disk instead of rows in a database. Simpler surface area, easier to
reason about, and it turns out a static site generator doesn't need an ORM.
The authentication question didn't stay unanswered, either - more on that separately, since it deserves its own post.