RSS feeds are a way for others to consume your content in their own feed without having to go to your website every time you publish a piece.
Astro gives you a package @astrojs/rss
that helps you create such a feed. On the Astro side, this will be an API route which we haven't touched on yet in this course but just know this is a route that others can hit to give them data, in this case a feed of all your posts.
Here we'll export a GET function that will return an RSS feed. RSS feeds require a certain shape to their data which is what we will provide the function. We'll give it a title, description, site, and items.
The items we'll grab from a call to getCollection
and each will have a title, description, publication date, link, and content. For the content, we are rendering the full post as html. To do this safely we will need to packages: markdown-it
, and sanitize-html
. markdown-it
will take our markdown and produce html and sanitize-html
will strip out any unnecessary HTML.
Lazar Nikolov: [0:00] RSS is a type of web feed that allows you to distribute your content to other individuals or aggregators. People have been using RSS to publish their blog posts, podcast episodes, or even video series, for a couple of decades now.
[0:15] Astro has a first-class support for RSS. To get started, first we're going to install the @astrojs/rss package. Since we're going to generate this file during build time, and we need an endpoint for it, we're going to open the pages directory and create a new page called feed.xml.ts. That's correct, that's not a typo.
[0:42] Since Astro reads the file name and creates the route according to that, creating files that have two file extensions like .xml.ts is a way to create an endpoint that seemingly points to a static file, but, in reality, it's an HTTP request handler that can do just about anything. We're going to use this trick again in this course.
[1:04] Let's bring in the RSS method from the @astrojs/rss package. We're also going to import the API context type from the Astro package. This type is going to give us typings for our endpoint handler. Then, we need to export an async function named get. We're going to accept the context in the argument. We'll set it to the API context type that we just imported.
[1:34] Now, we have an endpoint for our feed.xml file. Don't worry, we're going to cover endpoints in one of the later lessons as well, in much better detail. Let's proceed for now.
[1:44] We can invoke the RSS method now and return the result. This method is going to generate the actual RSS file for us according to how we configure it. Let's start configuring it. We'll add an object as the first argument, and now we can define a handful of properties like the description, items, site, title, etc.
[2:03] Let's start with the title, which we can set to something like Lazar Nikolov's blog. We can define the description. Next, we can define our site. We can try to obtain the site from the context. Context.site will give us the URL from the request if it exists. If not, we need to provide a fallback one.
[2:27] Lastly, we have the items. These are going to be our blog posts, and we need to bring them in with the getCollection method. Let's go up, import the getCollection from the astro-content package, grab the posts using it and use them as the value of the item's property.
[2:46] The item object must contain a few properties like the title, which we can obtain from the post.data.title. Then we have the description, we can set to post.data.description. If you don't have the description value in the article schema, you can either add it or, if you don't want a description for your RSS, you can just remove the whole property. It's not required.
[3:12] Then we have the pubDate, which will point to the post.data.date. We want to have the link as well. We can do /blog/post.slug, so the RSS readers can know how to open the article in a web browser.
[3:30] Lastly, we have the content, which represents the full content of the item. What's important here is that the content should be a valid HTML string, but the post.body only contains the markdown. Before we set the content, we first need to render the markdown into HTML, and then it's a good idea to sanitize that HTML.
[3:53] We're going to use two packages to achieve that. Let's first install the markdown-it, which will render the markdown into HTML and also sanitize-html, which is going to sanitize the HTML.
[4:10] These packages don't come with their typings, so we need to additionally install. We're going to pass save, dev, so they're not being treated as production dependencies @types/sanitize-html and @types/markdown-it.
[4:28] OK, we got the packages. Now let's use them. Let's bring in the sanitize-html from sanitize-html package and also the MarkdownIt from markdown-it. The default export of the markdown-it package is a class that we need to instantiate. Outside of the getFunction, we can do parser = new MarkdownIt. That's it.
[4:57] We can scroll down now to the body and wrap it with our parser.render. The render method is going to grab the markdown and render it into an HTML string, which we can pass into the sanitize-HTML method and have a clean, sanitized HTML as the content in our RSS, and that's it.
[5:20] Let's run the server now and open localhost 4321/feed.xml. Here's our RSS feed. There's our feed info. Then, we have all of our articles as items with their title, their link, their guide, which is automatically generated, the date of publication and, of course, the content as an HTML string.
[5:45] If we were to add our localhost feed.xml to an RSS reader, we'll be able to read our blog posts and also open them by clicking on the link. Since we defined the URL to be our deployment, and now the URL points to my website, of course, it's not going to work. It's important to note that we're rendering the whole article's content within the reader.
[6:10] What we could do next is to promote our RSS URL. Let's go to the layout, scroll down to the header and add a link to it, right after the blog. It'll point to /feed.xml. Let's confirm that we have it working. Here's the RSS link. If we click on it, we get the RSS feed. Our blog has an RSS feed now.
[6:32] Let's do a recap. Astro has a first-class support for RSS feeds. First, we installed the astrojs/rss package. Then, we created an endpoint file named feed.xml.ts into our pages' directory for our RSS feed. We exported the getFunction that first grabbed our blog collection and returned the result.
[6:54] We defined the properties and mapped through the blog collection to generate the RSS items. The content of the items must be valid HTML. We needed to pull in two more packages, the sanitize-html and the markdown-it. We used these two packages to sanitize and render the markdown into HTML.
[7:14] After we confirmed that the RSS feed is working correctly, we added a link to it in the header, so our visitors can use it in their RSS reader apps.