serve Atom feeds for the site, a section and a tag

Membership is a publication date, not a type declaration (ADR-0043). The parked
feed shape said "every type declared primary", which would have made feeds wait on
declared types a third time — but the thing that distinguishes a feed item is
already on disk. Pages and section landings drop out because they have no date,
which is the right reason. The parked idea stays parked with a sharper trigger:
someone wanting a *dated* bundle kept out.

Built with encoding/xml from typed structs, never a template: XML in html/template
is escaping for the wrong grammar, and that is a correctness trap rather than a
matter of taste.

A bug the evidence found, older than feeds: content.URL("", lang) built "//", so a
whole-site feed's id and alternate link were https://khosra.example// — every
entry identity wrong in every reader. The root is "/" now, with a test, and the
hand-built "/" the resolver carried for the same reason can follow later.

Two counters re-scoped rather than incremented, the same way transforms was:

Views now counts *per-bundle selection* — the thing architecture.md means by the
View layer, still at zero consumers. Output formats are not it: HTML, sitemap XML
and Atom are three functions with nothing to share, so an interface over them
would have one member and no leverage.

Effects stays at 1. A feed is generated per request like the sitemap, so it is not
a second Effect and the runner is not yet due — the next thing that writes files
off the request path is.
This commit is contained in:
2026-08-01 02:23:36 +06:00
parent 7da2a58fd5
commit 62e31215ec
11 changed files with 372 additions and 12 deletions
+11
View File
@@ -114,6 +114,17 @@ The set is overlaid the same way as the page kinds: a site's `templates/shortcod
the embedded one, so redefining `figure` replaces it and any fragment left alone is inherited. Argument
names are contract, added but never renamed.
## Feed discovery
The engine serves Atom at `/feed.xml`, per section and per tag (`content-model.md`). A theme advertises it from
the document head, which is what a reader looks for:
```
<link rel="alternate" type="application/atom+xml" href="{{.Site.Base}}/feed.xml" title="{{.Site.Title}}">
```
Only with a declared `base`: without one there is no feed to point at.
## The stability rule
Fields and names are **added, never renamed or removed**. Absence is always legal: a template reading a