How to add an RSS feed to your SvelteKit app

Written by Bahaa Zidan

  1. Install the Feed npm package to your project.
npm i feed
  1. Create a directory (folder) named rss.xml in your routes directory.

    • The name doesn’t matter. As long is it ends with .xml.
  2. Create a +server.ts file inside src/routes/rss.xml directory.

  3. In +server.ts file, export an async function named GET. This will expose an endpoint that responds with the rss.xml file.

export async function GET() {
  // ...
}
  1. Create a Feed instance. I think most of these properties are self explanatory.
import { Feed } from "feed";

export async function GET() {
  const feed = new Feed({
    title: "Gebna blog",
    description: "Gebna, GebnaTorky, or Bahaa Zidan's Blog",
    id: "https://gebna.gg/",
    link: "https://gebna.gg/",
    language: "en", // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
    favicon: "https://gebna.gg/favicon.ico",
    copyright: `Copyright ${new Date().getFullYear().toString()}, Bahaa Zidan / Gebna`,
    generator: "🍉", // optional, default = 'Feed for Node.js'
    feedLinks: {
      rss: "https://gebna.gg/rss.xml",
    },
    author: {
      name: "Gebna / Bahaa Zidan",
      email: "[email protected]",
      link: "https://gebna.gg/whoami",
    },
    ttl: 60,
  });
}
  1. Get the array of posts, articles, videos, or whatever you want to list in your feed. Here I implemented a getArticles function that returns an array of articles.
import { getArticles } from "$lib";
  1. Loop over the array of articles, add each article to the feed.
// ...

export async function GET() {
  // ...
  const articles = getArticles();
  for (const article of articles) {
    feed.addItem({
      title: article.title,
      description: article.description,
      content: `<p>${article.description}</p> <div style="margin-top: 50px; font-style: italic;"> <strong><a href="https://gebna.gg${article.path}">Keep reading</a>.</strong> </div> <br /> <br />`,
      link: `https://gebna.gg${article.path}`,
      author: [
        {
          name: "Gebna / Bahaa Zidan",
          email: "[email protected]",
          link: "https://gebna.gg/whoami",
        },
      ],
      date: new Date(article.publishDate),
    });
  }
}
  1. Finally, return a response with body feed.rss2(). Don’t forget the content type.
return new Response(feed.rss2(), {
  headers: {
    "Content-Type": "application/xml; charset=utf-8",
  },
});

Here’s the full src/routes/rss.xml/+server.ts file:

import { getArticles } from "$lib";
import { Feed } from "feed";

export async function GET() {
  const feed = new Feed({
    title: "Gebna blog",
    description: "Gebna, GebnaTorky, or Bahaa Zidan's Blog",
    id: "https://gebna.gg/",
    link: "https://gebna.gg/",
    language: "en", // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
    favicon: "https://gebna.gg/favicon.ico",
    copyright: `Copyright ${new Date().getFullYear().toString()}, Bahaa Zidan / Gebna`,
    generator: "🍉", // optional, default = 'Feed for Node.js'
    feedLinks: {
      rss: "https://gebna.gg/rss.xml",
    },
    author: {
      name: "Gebna / Bahaa Zidan",
      email: "[email protected]",
      link: "https://gebna.gg/whoami",
    },
    ttl: 60,
  });
  const articles = getArticles();

  for (const article of articles) {
    feed.addItem({
      title: article.title,
      description: article.description,
      content: `<p>${article.description}</p> <div style="margin-top: 50px; font-style: italic;"> <strong><a href="https://gebna.gg${article.path}">Keep reading</a>.</strong> </div> <br /> <br />`,
      link: `https://gebna.gg${article.path}`,
      author: [
        {
          name: "Gebna / Bahaa Zidan",
          email: "[email protected]",
          link: "https://gebna.gg/whoami",
        },
      ],
      date: new Date(article.publishDate),
    });
  }

  return new Response(feed.rss2(), {
    headers: {
      "Content-Type": "application/xml; charset=utf-8",
    },
  });
}