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:
@@ -575,3 +575,23 @@ core carries a generic "serve this directory of derived files" — which is the
|
||||
feature wants output of its own.
|
||||
Revisit if: startup time becomes noticeable on a large site — then the pass wants a manifest and a change
|
||||
check rather than a stat per candidate.
|
||||
|
||||
## ADR-0043 — A feed carries dated bundles; membership needs no type declaration
|
||||
Date: 2026-07-30 · Status: accepted (chooses a simpler rule than the parked feed shape in
|
||||
`ideas/deferred-decisions.md`, which waited on declared types)
|
||||
Decision: `/feed.xml` carries every **dated** bundle, newest first, capped at the most recent 20.
|
||||
`/{section}/feed.xml` and `/tags/{term}/feed.xml` narrow it through the same Query, and a `/{lang}/` prefix
|
||||
selects a language like anywhere else. The format is Atom, built with `encoding/xml` from typed structs rather
|
||||
than a template. A feed needs the site's `base`, and answers 404 without one. Entries carry title, link,
|
||||
identity and date — not the body.
|
||||
Why: the parked direction was "every type declared `primary`", which would have made feeds wait for declared
|
||||
types a third time. But the thing that actually distinguishes a feed item is already on disk: a publication
|
||||
date. Pages, colophons and section landings have none and drop out for the right reason rather than by
|
||||
declaration, and nothing new has to be invented or kept in sync. `encoding/xml` over a template because XML in
|
||||
`html/template` is escaping for the wrong grammar — a correctness trap, not a style preference.
|
||||
Consequence: cheap — one Query, one marshaller, and no new content concept; a `[spec]` idea stays parked
|
||||
instead of being half-built. Expensive — "in the feed" and "has a date" cannot yet be separated, so a dated
|
||||
bundle an author wants out of the feed has no way to say so; and entries without bodies mean a reader shows
|
||||
titles only, until `summary` is parsed.
|
||||
Revisit if: someone wants a dated bundle excluded, or one section kept out of the main feed. *That* is the
|
||||
real trigger for declared types, and it is now a sharper one than "feeds exist".
|
||||
|
||||
Reference in New Issue
Block a user