feat(feeds): publish an Atom feed for the blog alongside RSS #10

Merged
lytedev merged 1 commit from atom-feed into master 2026-08-06 10:44:38 -05:00
Owner

Adds an Atom feed at /blog/atom.xml, prompted by Chris Morgan's Atom > RSS. Both of his substantive complaints applied to this site's feed: RSS 2.0 never specified whether <title> is plain text or HTML, and it has no way to distinguish a summary from full content.

  • config.yaml: declare the application/atom+xml media type and an atom output format (Hugo has no built-in one), and move outputs from the bogus blog kind to section — Hugo only honours real page kinds, so that line was never doing anything.
  • layouts/_default/list.atom.xml: the feed template. Titles use type="text"; entries carry both <summary> and full <content>.
  • baseof.html: feed autodiscovery <link rel="alternate"> tags for both feeds.
  • index.html: link the Atom feed next to the existing RSS link.

RSS keeps being generated at /blog/index.xml, so existing subscribers are unaffected; the feeds cross-link via rel="alternate".

Verified: hugo builds clean and xmllint --noout public/blog/atom.xml passes, with all 10 posts present.

Adds an Atom feed at `/blog/atom.xml`, prompted by [Chris Morgan's *Atom > RSS*](https://chrismorgan.info/atom%3Erss). Both of his substantive complaints applied to this site's feed: RSS 2.0 never specified whether `<title>` is plain text or HTML, and it has no way to distinguish a summary from full content. - `config.yaml`: declare the `application/atom+xml` media type and an `atom` output format (Hugo has no built-in one), and move `outputs` from the bogus `blog` kind to `section` — Hugo only honours real page kinds, so that line was never doing anything. - `layouts/_default/list.atom.xml`: the feed template. Titles use `type="text"`; entries carry both `<summary>` and full `<content>`. - `baseof.html`: feed autodiscovery `<link rel="alternate">` tags for both feeds. - `index.html`: link the Atom feed next to the existing RSS link. RSS keeps being generated at `/blog/index.xml`, so existing subscribers are unaffected; the feeds cross-link via `rel="alternate"`. Verified: `hugo` builds clean and `xmllint --noout public/blog/atom.xml` passes, with all 10 posts present.
Chris Morgan's <https://chrismorgan.info/atom%3Erss> lays out where RSS 2.0
is genuinely underspecified, and both of his substantive complaints applied
to this site's Hugo-generated feed:

- RSS never specified whether <title> holds plain text or HTML, so readers
  guess and disagree once a title contains &, < or something that looks like
  an entity. Atom's text constructs make it explicit; entries here use
  type="text".
- RSS has one <description> with no way to say whether it is a summary or the
  whole post, so full-text readers silently show truncated content. Atom
  separates <summary> from <content>, and this feed now ships both.

Atom is not a built-in Hugo output format, so config.yaml declares the
application/atom+xml media type and an "atom" output format, and
layouts/_default/list.atom.xml renders it. The XML declaration goes through
printf|safeHTML because layouts are parsed as html/template, which would
otherwise escape the processing instruction.

The outputs key moved from the bogus "blog" kind (Hugo only honours real
page kinds, so that line was never doing anything -- the RSS feed came from
the default section outputs) to "section", which is what actually applies.

RSS keeps being generated at /blog/index.xml so existing subscribers are not
broken; the two feeds cross-link via rel="alternate", and both are exposed
for autodiscovery in <head>.
lytedev merged commit 898db5aec6 into master 2026-08-06 10:44:38 -05:00
lytedev deleted branch atom-feed 2026-08-06 10:44:40 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lytedev/site.lyte.dev!10
No description provided.