Home

Add Markdown blog server

Release #001

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/<slug> 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 Mobile

🤖 Generated with Claude Code