Skip to content

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.

Note

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.