Feeds
A feed turns a
content collection
into something readers subscribe to. Add
@jxsuite/feed
to
extensions
and declare which collection to syndicate:
{
"extensions": ["@jxsuite/parser", "@jxsuite/feed"],
"feed": {
"blog": {
"collection": "posts",
"basePath": "/blog/",
"title": "Example Blog"
}
}
}
The build writes
dist/feed.xml
and
dist/feed.json
, and adds the discovery links to every page's
<head>
so a browser or reader finds them on its own.
url
must be set in
project.json
— a feed's entries are identified by absolute URL, so there is nothing to generate without one.
Options
| Key | Default | What it does |
|---|---|---|
collection |
the key | Which content collection to syndicate |
basePath |
— | URL prefix the entries are served under, e.g.
/blog/ |
title
,
description |
— | Feed metadata |
formats |
["atom", "json"] |
Which documents to write |
output |
/feed |
Base path;
.xml
and
.json
are appended |
pageSize |
20 |
Entries in the subscription document |
archive |
false |
Write older entries to archive documents |
author |
— | { name, uri, email }
, overridden per entry by an
author
field |
dateField
,
updatedField |
date
,
updated |
Which frontmatter fields carry the timestamps |
contentMode |
"summary" |
full
adds the entry body beside the summary;
summary
omits it |
language |
defaults.lang |
BCP 47 tag |
Dates
Feed timestamps come from your frontmatter. Declare the field with a
format
so the loader normalizes it:
{ "properties": { "date": { "type": "string", "format": "date" } } }
An entry with no date falls back to the source file's modification time. The feed's own timestamp is the newest entry — never the build time, so redeploying does not re-notify everyone who subscribes.
Long histories
With
archive: true
, entries past
pageSize
are written to
/feed/archive/1.xml
,
2.xml
and so on, linked in both directions (
RFC 5005
). Archive 1 is the oldest and stays put as you publish — only the newest archive grows — so a reader that already fetched an archive never needs it again.
When a feed contains your entire history it says so, and readers can stop looking for more.
One feed per language
If the feed's collection keeps one directory per locale , you get one feed per language — no extra configuration:
| File | Holds | Says |
|---|---|---|
/feed.xml |
the English posts | xml:lang="en" |
/fr-ca/feed.xml |
the French posts | xml:lang="fr-CA" |
/ar/feed.xml |
the Arabic posts | xml:lang="ar" |
Item links point into that language's URL space too, so a French subscriber who clicks through lands on the French post rather than the English one.
Every page advertises all of them, each tagged with
hreflang
— the discovery links are written before the build knows which language the page is in, so they name every language and let the reader's client choose.
One feed carrying three languages would deliver every post three times to every subscriber, twice in a language they don't read. That's why the split isn't optional.
Why not RSS?
RSS 2.0 has no standards body, its date format is a 1982 email spec, and its
<guid>
semantics were never pinned down. Atom is an IETF standard with required identity and timestamps, and every reader made in the last twenty years handles it. If you need RSS for a specific consumer, open an issue with the case.
Related
Content collections — the source a feed reads
SEO and metadata — how the discovery links join the rest of
<head>Build output — where the feed files land in
dist/