Proper websites, done properly

Part 7: RSS feeds and sitemaps

6 minute read time / 759 words

Now we've got content, listings, and tags it'd be great to get sitemaps and news feeds running so we can share our content with the World (and search engines!) more easily

Install the RSS integration

Astro provides an RSS integration already, so we can just go ahead and install it and let it handle the heavy lifting for us.

npm install @astrojs/rss

We need to add a line into our Astro config file too, so open up astro.config.mjs and add the 'site' line in there:

import { defineConfig } from 'astro/config';

import mdx from "@astrojs/mdx";

// https://astro.build/config
export default defineConfig({
    integrations: [mdx()],
    site: "https://mysexyastro.site",
});

Create the basic news feed

Now we're ready to start pulling our content together for the feed. The Astro documentation has a tutorial on how to create a feed from globbing through folders for markdown files, but we want to be specific here. As a news feed, we probably want to show our blog posts first and foremost, so ideally we want to just get all the posts in the post content collection we created.

Fortunately, we've already done that extra step in creating our listing and tags pages previously. We can combine both bits together. Create a new file at /feed.xml.js and put this in it:

import { getCollection } from 'astro:content';
import rss from '@astrojs/rss';

export async function GET(context) {
    const postEntries = await getCollection('posts', ({ data }) => {
        return data.isDraft !== true;
    });

    return rss({
        title: 'My Sexy Asto Site | Pages',
        description: 'We did some sexy things and made an Astro site',
        site: context.site,
        items: postEntries.map((post) => ({
            title: post.data.title,
            pubDate: post.data.publishedDate,
            description: post.data.description,
            customData: post.data.customData,
            link: `/posts/${post.slug}/`,
        })),
        customData: `<language>en-GB</language>`,
    });
}

Can't find the feed?

RSS feeds are only built during build time, not while you're in dev mode. To see your sitemap working, you'll need to quit your running local server, and do an npm run build followed by an npm run preview which will allow you to see what a production build would look like.

You'll be able to go to http://localhost:4321/feed.xml to see the sitemap working here.

Add our content to each feed item

You will often find either entire contents of an article or at least a good preview chunk in RSS feeds. We can do that here too with a little help from a Markdown parser and a HTML sanitizer to make all our content's HTML elements safe to put into XML documents.

First, install the new packages we need:

npm install sanitize-html markdown-it

We can now import those, and configure them to get a post's content and parse and sanitize them ready for XML consumption. Update our feed.xml.js file like so:

import { getCollection } from 'astro:content';
import rss from '@astrojs/rss';
import sanitizeHtml from 'sanitize-html';
import MarkdownIt from 'markdown-it';

const parser = new MarkdownIt();

export async function GET(context) {
    const postEntries = await getCollection('posts', ({ data }) => {
        return data.isDraft !== true;
    });

    return rss({
        title: 'My Sexy Asto Site | Pages',
        description: 'We did some sexy things and made an Astro site',
        site: context.site,
        items: postEntries.map((post) => ({
            title: post.data.title,
            pubDate: post.data.publishedDate,
            description: post.data.description,
            customData: post.data.customData,
            content: sanitizeHtml(parser.render(post.body)),
            link: `/posts/${post.slug}/`,
        })),
        customData: `<language>en-GB</language>`,
    });
}

If you run a build and preview again, you'll now see page content in the feed too. We can enable autodiscovery of our feed by adding the relevant meta tag to our layout template's <head>.

<link rel="alternate" type="application/rss+xml" title="My Sexy Astro Site" href={`${Astro.site}rss.xml`} />

Sitemaps

In a similar vein to RSS feeds, Astro has an official sitemap integration we can use here. Let's go ahead and install that now.

npx astro add sitemap

Accept the prompts and let Astro automatically update our config files and we're done. Honestly. That's it. The sitemap integration runs at build time like the RSS feed integration so you'll need to quit dev mode and do a build and preview run, but once you're on the preview site, you can visit http://localhost:4321/sitemap-index.xml and here's your sitemap index of sitemaps.

There'll only be one listed for now at http://localhost:4321/sitemap-0.xml which, if you visit, you'll see that it's automatically added all our dynamic URLs.