Browse Source

Add pull-releases records with screenshots

One folder per PR holding a README.md (title and changes) plus desktop
and mobile screenshots, so the PR text and visuals are kept in the repo.
Includes records for the two merged PRs and this one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude 2 days ago
parent
commit
2802c5c3dc

+ 35 - 0
pull-releases/001-initial/README.md

@@ -0,0 +1,35 @@
+# 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/<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](desktop.png) | ![Mobile](mobile.png) |
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)

BIN
pull-releases/001-initial/desktop.png


BIN
pull-releases/001-initial/mobile.png


+ 32 - 0
pull-releases/002-header-about-config/README.md

@@ -0,0 +1,32 @@
+# Add About page, configurable Home link, RSS footer, MIT license
+
+Branch `feature/header-about-config` · merged 2026-10-24 · version 0.2.0
+
+## What changed
+
+- **Header:** the host name is replaced by a **Home** link to the index, and the RSS link is replaced by **About**.
+- **Configurable Home text:** set `"homeText"` in `content/site.json`. With no file, no setting or a blank value, it shows "Home". The file is reloaded when it changes, so editing it needs a redeploy but not a rebuild or restart.
+- **About page (`/about`):** a box at the top with the version (0.2.0 plus the short git commit), the total post count and a link to the latest post. Below it is the guide to writing posts, taken from the hello-world post (`about.md`, built into the binary).
+- **Footer:** a new footer with the RSS link at the bottom right, on every page.
+- **License:** MIT in `LICENSE`, linked from the README. The README also documents `site.json`, `/about` and how versioning works.
+
+## Notes
+
+- `site.json` lives in `content/`, so `deploy-go posts --content` ships it with no script change. It is never treated as a post.
+- If `site.json` has invalid JSON or a misspelled setting name, the error is logged and the last good settings stay in use.
+
+## Testing
+
+- All tests pass with the race detector (`go test -race ./...`).
+- New tests cover each `site.json` case (missing, set, left out, blank, broken JSON, unknown setting, deleted), the header and footer on every page type, the About page with and without posts, and `site.json` not being listed as a post.
+- Built and ran locally, then checked the header, footer and About page in the HTML.
+
+## Screenshots
+
+Taken afterwards from a build of the branch's final commit (`ac317db`).
+
+| Desktop | Mobile |
+|---|---|
+| ![Desktop](desktop.png) | ![Mobile](mobile.png) |
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)

BIN
pull-releases/002-header-about-config/desktop.png


BIN
pull-releases/002-header-about-config/mobile.png


+ 31 - 0
pull-releases/003-css-cache-busting/README.md

@@ -0,0 +1,31 @@
+# Add content hash to stylesheet URL; start pull-releases records
+
+Branch `feature/css-cache-busting` · version 0.2.1
+
+## What changed
+
+- **Hashed stylesheet URL:** pages link to `/static/style.css?v=<hash>`, where `<hash>` is the first 10 hex digits of the stylesheet's SHA-256. A changed stylesheet gets a new URL, so browsers fetch it on the next page load with no hard refresh needed.
+- **Caching:** requests carrying the current hash are cached for a year (`immutable`). Plain or outdated URLs keep the 1-hour cache.
+- **Pull-release records:** new `pull-releases/` folder with one subfolder per PR, each holding a `README.md` (title and changes) and desktop and mobile screenshots. Records for the two earlier PRs are included, with screenshots taken from builds of their final commits.
+- **Version:** 0.2.1.
+
+## Notes
+
+- There is no visible change in this PR; the screenshots match 002.
+- `pull-releases/` is not part of the app: it isn't built into the binary or deployed.
+
+## Testing
+
+- All tests pass with the race detector (`go test -race ./...`).
+- New test: the link's hash matches the file's SHA-256, plus Cache-Control for the hashed, plain and wrong-hash URLs.
+- Built and ran locally; the hash matched `sha256sum static/style.css` and the cache headers were correct.
+
+## Screenshots
+
+From the branch's build (`a5ee315`) running locally.
+
+| Desktop | Mobile |
+|---|---|
+| ![Desktop](desktop.png) | ![Mobile](mobile.png) |
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)

BIN
pull-releases/003-css-cache-busting/desktop.png


BIN
pull-releases/003-css-cache-busting/mobile.png


+ 27 - 0
pull-releases/README.md

@@ -0,0 +1,27 @@
+# Pull releases
+
+One folder per pull request, so each change has a written record with
+screenshots. The record is added on the PR's own branch, so it is reviewed and
+merged with the change.
+
+```
+pull-releases/
+  NNN-branch-name/      NNN = next number in sequence, branch name without feature/
+    README.md           title (first line), what changed, notes, testing
+    desktop.png         home page at 1280×900
+    mobile.png          home page at 390×844 (2× pixel density)
+```
+
+To open the PR on Gogs, use the compare link for the branch, paste the first
+line of `README.md` as the title and the rest as the description.
+
+Screenshots are taken from the branch's build running locally, before it is
+deployed, so they show exactly what the PR will put live. When a PR mainly
+changes a page other than the home page, that page is captured as well (for
+example `about-desktop.png`).
+
+| PR | Change |
+|---|---|
+| [001](001-initial/) | Markdown blog server |
+| [002](002-header-about-config/) | About page, configurable Home link, RSS footer, MIT license |
+| [003](003-css-cache-busting/) | Content hash on the stylesheet URL; this folder |