# posts A small Go application that serves a Markdown blog at . Each Markdown file in `content/` is one blog post. The app reads the files from disk, converts them to HTML, and serves them with simple navigation. Adding or editing a post does not require restarting the app. ## Writing a post Create `content/YYYY-MM-DD-slug.md`. Front matter is optional: ```markdown --- title: My first post date: 2026-10-24 summary: One line shown on the index page. draft: false --- Post body in Markdown... ``` - **title** — falls back to the first `# heading`, then the slug. - **date** — falls back to the date in the filename. - **summary** — shown on the index page. - **draft: true** — hides the post everywhere. The URL is `/posts/`, where the slug is the filename without the date prefix and `.md` extension. Posts go through the normal branch-and-PR flow; never push to `main`. ## Pages | Route | Page | |---|---| | `/` | All posts, newest first | | `/posts/` | One post, with previous/next links | | `/feed.xml` | RSS feed | | anything else | 404 page | Markdown is rendered with [goldmark](https://github.com/yuin/goldmark) (CommonMark plus GitHub-style tables, strikethrough and autolinks). Raw HTML in posts is not rendered. ## Configuration Environment variables (on the server, in `/etc/goapps/posts.env`): | Variable | Default | Meaning | |---|---|---| | `PORT` | (required) | Port to listen on, bound to `127.0.0.1` | | `CONTENT_DIR` | `content` | Directory holding the `.md` posts | | `SITE_URL` | `https://posts.monoaf.com` | Absolute base URL used in the RSS feed | ## Development ```sh go test ./... PORT=8080 go run . ``` ## Deployment Runs as systemd unit `goapp@posts` on port 8002 behind nginx. Deploy with: ```sh deploy-go posts --content ``` which builds and installs the binary and syncs `content/` to `/opt/apps/posts/content/`.