Skip to content

feat(blog): add RSS feed at /blog/rss.xml#149

Merged
rubenhensen merged 2 commits into
mainfrom
feat/blog-rss-feed
May 7, 2026
Merged

feat(blog): add RSS feed at /blog/rss.xml#149
rubenhensen merged 2 commits into
mainfrom
feat/blog-rss-feed

Conversation

@rubenhensen

Copy link
Copy Markdown
Contributor

Summary

  • Adds a prerendered RSS 2.0 feed at /blog/rss.xml, generated from each post's .svx frontmatter (title, description, date, author).
  • Exposes the feed via <link rel="alternate" type="application/rss+xml"> on the blog index for reader autodiscovery.
  • Adds a small RSS button next to the blog heading so visitors can subscribe directly.

Implementation notes

  • Mirrors the style of src/routes/sitemap.xml/+server.js (vanilla JS + JSDoc, prerender = true, import.meta.glob over /src/content/blog/*.svx).
  • Sorts items newest-first; lastBuildDate tracks the most recent post.
  • All frontmatter values are XML-escaped before embedding.

Test plan

  • npm run build succeeds and emits build/blog/rss.xml.
  • npx svelte-check passes (0 errors / 0 warnings).
  • npx eslint and npx prettier --check pass on the changed files.
  • Validate generated XML at https://validator.w3.org/feed/ after deploy.
  • Confirm an RSS reader (e.g. NetNewsWire / Feedly) can discover and subscribe to the feed from /blog.

Generates an RSS 2.0 feed from the blog .svx frontmatter, exposes it via
<link rel="alternate"> for autodiscovery, and adds a visible RSS button on
the blog index so readers can subscribe.
@rubenhensen

Copy link
Copy Markdown
Contributor Author

/dobby review this PR

@dobby-coder

dobby-coder Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Dobby is on it! Dobby will review this pull request very carefully and report back with findings, sir!

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Looks good overall — clean implementation that mirrors sitemap.xml/+server.js, builds cleanly, and produces valid RSS. Approving with a few small, non-blocking suggestions.

Verified locally

  • npm ci --legacy-peer-deps && npm run build succeeds; build/blog/rss.xml is emitted with both posts in newest-first order.
  • npx svelte-check --threshold warning → 0 errors / 0 warnings.
  • npx prettier --check and npx eslint clean on the changed files.
  • Generated XML is well-formed; frontmatter is correctly XML-escaped (e.g. '&apos; in the "Looking ahead" description).

Strengths

  • Uses prerender = true plus import.meta.glob(..., { eager: true }), so the feed is a static file at deploy time — no runtime cost and no SSR surprises with adapter-static.
  • escapeXml covers all five XML predefined entities and tolerates null/undefined via String(value ?? '').
  • toRfc822 falls back to "now" on invalid dates instead of emitting Invalid Date.
  • Autodiscovery <link rel="alternate" type="application/rss+xml"> on the blog index is exactly what feed readers look for.
  • PR title is conventional-commit (feat(blog): …), so pr-title.yml will pass.

Suggestions (non-blocking)

  1. Trailing-slash mismatch with canonical URLs. The marketing layout sets trailingSlash = 'always' (from PR #104), so the actual canonical URLs are https://postguard.eu/blog/<slug>/. The feed emits https://postguard.eu/blog/<slug> (no trailing slash) for both <link> and <guid isPermaLink="true">. Aggregators that dedupe by GUID or canonical URL may treat these as different from the on-page canonical / sitemap entries. Suggest:

    const url = `${SITE_URL}/blog/${post.slug}/`

    to match sitemap.xml/+server.js (https://postguard.eu${e.path}/) and SEO.svelte's derived canonical.

  2. Hardcoded <language>en</language>. The site ships en and nl translations. The current .svx files in src/content/blog/ are English-only, so en is correct today, but worth a // TODO if multi-language posts are on the roadmap (one feed per locale is the usual pattern).

  3. description could use CDATA if HTML ever sneaks into frontmatter. Today the descriptions are plain text and escaping is sufficient; if you later allow inline markup in description, switch to:

    <description><![CDATA[...]]></description>

    Not needed now.

  4. <dc:creator> is good, but RSS 2.0's native <author> field expects an email address, which you're (correctly) not exposing. The dc:creator choice is the right one — no change requested, just calling it out for future readers.

  5. Optional polish: add the same autodiscovery <link> to individual blog post pages (/blog/[slug]) so a reader visiting a single post can also subscribe. Not required.

Test plan items still pending

  • Validating at https://validator.w3.org/feed/ post-deploy — the local output looks compliant, but a real validator run is the right backstop.
  • Reader autodiscovery from /blog.

Ship it after addressing (1) if you agree the canonical URL should match the rest of the site; everything else is taste.

…r from posts

Marketing routes use trailingSlash = 'always', so the feed's <link> and
<guid isPermaLink="true"> values now end in '/' to match the on-page
canonical and sitemap entries — preventing aggregators from treating the
feed and the canonical as separate items.

Also adds the RSS autodiscovery <link> to individual blog posts so
readers visiting a single article can subscribe.
@rubenhensen

Copy link
Copy Markdown
Contributor Author

/dobby please re-review — addressed the trailing-slash mismatch (channel link, item links, and GUIDs now end in / to match the canonical URLs and sitemap) and added RSS autodiscovery to individual blog post pages. Skipped the language TODO, CDATA, and dc:creator notes per your guidance that they were non-blocking / not needed today.

@rubenhensen

Copy link
Copy Markdown
Contributor Author

/dobby add the manual testing to encryption4all/postguard-business#48

@dobby-coder

dobby-coder Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Dobby is on it! Dobby will check the trailing-slash fixes and the RSS autodiscovery additions, and report back with a fresh review. Dobby thanks you for addressing the feedback so quickly!

@dobby-coder

dobby-coder Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

This agent is on it! Eager to copy the manual testing notes over to postguard-business issue 48 right away!

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review summary

Fixes look great — approving. Both follow-ups from the prior review are in place and verified locally.

Verified locally

  • npm ci --legacy-peer-deps && npm run build succeeds; build/blog/rss.xml is emitted.
  • Channel <link>, item <link>, and <guid isPermaLink="true"> all end in / now, matching trailingSlash = 'always' and the sitemap entries — aggregators will no longer see the feed and the canonical as separate items.
  • RSS autodiscovery <link rel="alternate" type="application/rss+xml" href="/blog/rss.xml"> is now present in the built HTML for /blog/, /blog/looking-ahead-with-postguard/, and /blog/introducing-postguard/.
  • npx svelte-check --threshold warning → 0 errors / 0 warnings / 0 files with problems.
  • npx prettier --check and npx eslint clean on the changed files.
  • Generated XML parses cleanly (well-formed).

Spot-check of generated feed

<channel>
  <link>https://postguard.eu/blog/</link>
  ...
  <item>
    <link>https://postguard.eu/blog/looking-ahead-with-postguard/</link>
    <guid isPermaLink="true">https://postguard.eu/blog/looking-ahead-with-postguard/</guid>

Skipped items (acknowledged)

  • Hardcoded <language>en</language> TODO — fine, posts are English-only today.
  • CDATA wrap for description — not needed while frontmatter stays plain text.
  • <author> vs <dc:creator>dc:creator remains the right call (no email exposure).

Still pending (deploy-time, not blockers)

LGTM — ship it.

@dobby-coder

dobby-coder Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Added the manual testing for this PR to the staging checklist as §8 "postguard.eu — blog RSS feed": encryption4all/postguard-business#48 (comment)

@rubenhensen rubenhensen merged commit 8adcdaf into main May 7, 2026
7 checks passed
@rubenhensen rubenhensen deleted the feat/blog-rss-feed branch May 7, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant