# Add Markdown blog server Branch `feature/initial` · merged 2026-10-24 · version (none; later called 0.1.0) ## What changed - **Blog server:** a Go app that serves each `content/*.md` file as a blog post. - `/` lists all posts, newest first, with title, date and summary. - `/posts/` shows one post, with links to the newer and older posts. - `/feed.xml` is an RSS feed of the 20 newest posts. - Any other URL gets a styled 404 page. - **Posts:** named `YYYY-MM-DD-slug.md`, with an optional front-matter block for `title`, `date`, `summary` and `draft`. If the title is missing, the first `# Heading` is used, then the slug. If the date is missing, it comes from the filename. - **Live content:** posts are re-read whenever a file in the content directory is added, changed or removed, so new posts appear without a restart. - **Fault tolerance:** a post with a bad filename or broken front matter is skipped and logged; the rest of the site keeps working. - **Markdown:** rendered with goldmark (CommonMark plus GitHub-style tables, strikethrough, task lists and autolinks). Raw HTML in posts is left out. - **Templates and CSS:** built into the binary. The layout is minimal, with automatic dark mode. - **Security:** URLs can only reach posts that have been indexed, so `../` paths get a 404. Responses carry a strict Content-Security-Policy (no scripts), `nosniff` and a referrer policy. The server binds to `127.0.0.1` with request timeouts. - **Configuration:** set by environment variables `PORT`, `CONTENT_DIR` and `SITE_URL`. - **First post:** `content/2026-10-24-hello-world.md`, a guide to writing posts covering file names, the header block, publishing, and what Markdown is supported. ## Testing - `go vet` is clean and all tests pass with the race detector (`go test -race ./...`), with 81% coverage. - Tests cover front-matter parsing and fallbacks, CRLF files, drafts, ordering, newer/older links, 404s including path-traversal attempts, the RSS feed, static files, security headers, and picking up added and removed posts. - Built and ran locally against the real `content/`, then checked the index, the post and the feed. ## Screenshots Taken afterwards from a build of the branch's final commit (`0bd42c4`). | Desktop | Mobile | |---|---| | [![Desktop](desktop.png)](desktop.png) | [![Mobile](mobile.png)](mobile.png) | 🤖 Generated with [Claude Code](https://claude.com/claude-code)