Skip to main content

flexweg-rss

The flexweg-rss plugin generates RSS 2.0 feeds for your public site — one site-wide feed and as many per-category feeds as you want. Items are sorted newest-first; each carries title, description, link, pubDate, author, and an optional enclosure for the hero image.

What it generates

FeedPath on FlexwegDefault item count
Site-wide/rss.xml20
Per category/<category-slug>/<category-slug>.xml20 (configurable per feed)
Stylesheet/rss.xml.xsl(one, shared)

Per-category feeds use a doubled slug (/news/news.xml rather than /news/index.xml) so the file doesn't collide with the category archive HTML at /news/index.html.

The XSL stylesheet renders feeds as a styled HTML table when opened directly in a browser — RSS readers ignore the <?xml-stylesheet?> PI and parse the XML normally.

Settings

/settings/plugin/flexweg-rss exposes:

Site feed tab

  • Enable site feed — toggle.
  • Item count — 1-100 (default 20). Most recent N online posts.
  • Excluded categories — categories whose posts should not appear in the site feed (e.g. "Internal updates"). Empty = include everything.
  • Add to footer menu — when on, the plugin injects a RSS entry into the resolved footer menu (no MenusPage edit needed).

Category feeds tab

  • A list of (category, item count, addToFooter) rows.
  • Add feed picker shows only categories that don't already have one.
  • Remove deletes the row and the feed file on the next regeneration.

Force regenerate

Re-uploads every enabled feed from scratch + the XSL stylesheet. Useful after large config changes.

How items are built

Each <item> carries:

  • <title>post.title
  • <link> — absolute URL via pathToPublicUrl(baseUrl, lastPublishedPath)
  • <guid isPermaLink="true"> — same as <link>
  • <description>post.excerpt when set, otherwise markdownToPlainText(post.contentMarkdown, 300) (first 300 chars of plain text)
  • <pubDate> — RFC-822-formatted publishedAt (fallback updatedAt then createdAt)
  • <author> — author's display name when available
  • <enclosure> — when post.heroMediaId is set, points at the large variant (fallback chain: largedefaultFormat → first available)

Sort order: publishedAt DESC, with updatedAt / createdAt as fallbacks.

How it hooks in

The plugin subscribes to three lifecycle actions:

api.addAction("publish.complete", regenerate);
api.addAction("post.unpublished", regenerate);
api.addAction("post.deleted", regenerate);

Each handler:

  1. Regenerates the site feed — unless post.primaryTermId is in excludedTermIds (in which case the post wouldn't appear anyway, and the existing file already excludes it).
  2. Regenerates the category feed matching post.primaryTermId, when one exists.
  3. Persists path bookkeeping — lastPublishedPath for each feed, plus orphan-feed cleanup when a category is deleted.

It also registers a filter on menu.json.resolved to append RSS items to the footer (driven by per-feed addToFooter flags) and a Regeneration target so Themes → Regenerate site → RSS feeds runs the full pass.

When skipped

  • settings.baseUrl is empty — feed <link> elements need an absolute origin. Logs a warning and exits.
  • Site feed disabled AND no category feeds configured — nothing to do; short-circuits without uploading.

Stale path cleanup

When a category's slug changes, the next regeneration:

  1. Deletes the file at the old lastPublishedPath.
  2. Uploads the new file at the new path.
  3. Updates lastPublishedPath in pluginConfigs.flexweg-rss.

Same flow when a feed is disabled (added to removedFeeds[] for one-shot cleanup).

Setting Add to footer on a feed appends a ResolvedMenuItem to the footer of /menu.json. Labels come from the plugin's i18n bundle:

  • Site feed → RSS
  • Category feed → RSS — {{category name}}

Items append at the end of the existing footer. There's no reordering UI — admins wanting custom placement should leave the toggle off and add the feed URL by hand in Menus.

The settings page Save handler patches pluginConfigs.flexweg-rss and immediately re-runs publishMenuJson(...) so footer changes go live without waiting for the Firestore subscription to round-trip.

Toggle

Plugins → Plugins tab → flexweg-rss card → Enable / Disable.

Disabling does not delete feed files already on Flexweg. To clean up after a disable, use Force regenerate first to record current paths, then delete the files via Flexweg's file manager.

When changes apply

ActionFiles updatedLatency
Publish a postSite feed (if not excluded) + matching category feedWithin seconds
Unpublish / deleteSameWithin seconds
Edit settingsAffected feeds + /menu.jsonOn Save
Slug change on a categoryOld feed deleted, new feed uploadedOn the next publish in that category

Internal details

  • Source: src/plugins/flexweg-rss/
  • External in production builds: yes
  • Hooks used: publish.complete, post.unpublished, post.deleted actions; menu.json.resolved filter; registerRegenerationTarget
  • Storage paths: /rss.xml, /<category-slug>/<category-slug>.xml, /rss.xml.xsl
  • Translations: 7 locales

Continue