feat(feeds): publish a JSON Feed for the blog #11

Merged
lytedev merged 1 commit from json-feed into master 2026-08-06 10:45:05 -05:00
Owner

Stacked on #10base is atom-feed, not master. Merge that one first.

Adds JSON Feed 1.1 at /blog/feed.json.

Unlike #10 this isn't a correctness fix — Atom already resolved the RSS ambiguities. JSON Feed just makes the feed trivial to consume from a script, and the modern indie readers (NetNewsWire, Feedbin, Inoreader, Miniflux) support it. Everything else still has Atom and RSS.

  • config.yaml: application/feed+json media type + a jsonfeed output format.
  • layouts/_default/list.jsonfeed.json: the template. Assembles a map and hands it to jsonify so Go does the string escaping, and runs as isPlainText: true so html/template doesn't mangle post content on its way into the JSON.
  • baseof.html / index.html: autodiscovery tag and homepage link.

summary is plainified, since JSON Feed specifies it as plain text (Atom's summary carries a type attribute and can hold HTML).

Verified: hugo builds all three feeds, jq parses feed.json with 10 items and content_html intact, and the Atom feed still passes xmllint.

Stacked on #10 — **base is `atom-feed`, not `master`.** Merge that one first. Adds [JSON Feed 1.1](https://www.jsonfeed.org/version/1.1/) at `/blog/feed.json`. Unlike #10 this isn't a correctness fix — Atom already resolved the RSS ambiguities. JSON Feed just makes the feed trivial to consume from a script, and the modern indie readers (NetNewsWire, Feedbin, Inoreader, Miniflux) support it. Everything else still has Atom and RSS. - `config.yaml`: `application/feed+json` media type + a `jsonfeed` output format. - `layouts/_default/list.jsonfeed.json`: the template. Assembles a map and hands it to `jsonify` so Go does the string escaping, and runs as `isPlainText: true` so html/template doesn't mangle post content on its way into the JSON. - `baseof.html` / `index.html`: autodiscovery tag and homepage link. `summary` is plainified, since JSON Feed specifies it as plain text (Atom's `summary` carries a `type` attribute and can hold HTML). Verified: `hugo` builds all three feeds, `jq` parses `feed.json` with 10 items and `content_html` intact, and the Atom feed still passes `xmllint`.
Builds on the Atom feed by adding JSON Feed 1.1
<https://www.jsonfeed.org/version/1.1/> at /blog/feed.json.

This is ergonomics rather than a correctness fix -- Atom already resolved the
RSS ambiguities that prompted the previous commit. JSON Feed just makes the
feed trivial to consume from a script, and the modern indie readers
(NetNewsWire, Feedbin, Inoreader, Miniflux) support it. Readers that do not
still have Atom and RSS.

The document is assembled as a map and handed to jsonify so that Go handles
string escaping instead of the template hand-rolling it. That is also why the
output format is isPlainText: true -- html/template would otherwise escape
post content on its way into the JSON string, exactly the way it mangled the
XML declaration in the Atom template.

summary is plainified because JSON Feed specifies it as plain text, unlike
Atom's summary, which carries a type attribute and can hold HTML.
lytedev changed target branch from atom-feed to master 2026-08-06 10:44:40 -05:00
lytedev merged commit 18cff20875 into master 2026-08-06 10:45:05 -05:00
lytedev deleted branch json-feed 2026-08-06 10:45:06 -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!11
No description provided.