Overview
trunkcms is a small, stateless blog engine in Go. Content lives in a GitHub repository, and GitHub is the only external service it needs.
Editors sign in with GitHub and write Markdown in a web UI at /admin. Every save is a commit. Each running instance picks up new commits, rebuilds the site, and swaps it in with no downtime.
The core idea
The Git repo is the database, and each instance is a cache. When a new commit shows up, an instance streams the repo tarball at that SHA to local disk, renders the whole site into a content-addressed file store, and atomically swaps a pointer to the new URL index.
“Rebuild and redeploy” happens inside the process, not as a new container deploy. That has a few consequences:
- It works the same on every platform. There’s no per-platform deploy pipeline and no cloud credentials in GitHub.
- A change goes live in seconds, not minutes.
- The container image is only the engine, so a content change never needs an image rebuild.
How changes arrive
Replicas are independent, and a webhook only reaches one of them, so there are three triggers. All of them lead to the same sync:
- Webhook. A push to the configured branch syncs the replica that receives it right away.
- Read-your-writes. The replica that made a commit syncs to it immediately, so editors see their change.
- Polling. A conditional request for the branch head. A
304costs nothing against the rate limit. The default interval is 30 seconds.
Failed builds never replace a good site. If a build fails, the previous output keeps serving and the error shows up in the admin dashboard. The admin UI also validates before committing, so most bad saves never reach Git.
Where to next
- Getting started: run it locally, then against GitHub.
- Content repo: posts, pages, bundles, front matter and
site.yaml. - Roles & permissions: who can do what.
- Themes: how this site’s theme works, and how to write your own.
- Configuration: every environment variable.