RSS

Astro supports fast, automatic RSS feed generation for blogs and other content websites. For more information about RSS feeds in general, see aboutfeeds.com.

The @astrojs/rss package provides helpers for generating RSS feeds using API endpoints. This unlocks both static builds and on-demand generation when using an SSR adapter.

First, install @astrojs/rss using your preferred package manager:

npm install @astrojs/rss

Then, ensure you’ve configured a site in your project’s astro.config. You will use this to generate links to your RSS articles.

Now, let’s generate our first RSS feed! Create an rss.xml.js file under your src/pages/ directory. rss.xml will be the output URL, so feel free to rename this if you prefer.

Next, import the rss helper from the @astrojs/rss package and call with the following parameters:

src/pages/rss.xml.js
import rss from '@astrojs/rss';

export function get(context) {
  return rss({
    // `<title>` field in output xml
    title: 'Buzz’s Blog',
    // `<description>` field in output xml
    description: 'A humble Astronaut’s guide to the stars',
    // Pull in your project "site" from the endpoint context
    // https://docs.astro.build/en/reference/api-reference/#contextsite
    site: context.site,
    // Array of `<item>`s in output xml
    // See "Generating items" section for examples using content collections and glob imports
    items: [],
    // (optional) inject custom xml
    customData: `<language>en-us</language>`,
  });
}

The items field accepts a list of RSS feed objects, each with a link, title, pubDate, and optional description, content, and customData fields. You can generate this array from a content collection or by using glob imports.

To create an RSS feed of pages managed in content collections, you use the getCollection() function to retrieve the list your of items.

src/pages/rss.xml.js
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';

export async function get(context) {
  const blog = await getCollection('blog');
  return rss({
    title: 'Buzz’s Blog',
    description: 'A humble Astronaut’s guide to the stars',
    site: context.site,
    items: blog.map((post) => ({
      title: post.data.title,
      pubDate: post.data.pubDate,
      description: post.data.description,
      customData: post.data.customData,
      // Compute RSS link from post `slug`
      // This example assumes all posts are rendered as `/blog/[slug]` routes
      link: `/blog/${post.slug}/`,
    })),
  });
}

You can configure your collection schema to enforce these expected RSS properties. Import and apply rssSchema to ensure that each collection entry produces a valid RSS feed item.

src/content/config.ts
import { rssSchema } from '@astrojs/rss';

const blog = defineCollection({
  schema: rssSchema,
});

export const collections = { blog };
Added in: @astrojs/rss@2.1.0 New

To create an RSS feed from documents in src/pages/, use the pagesGlobToRssItems() helper. This accepts an import.meta.glob result and outputs an array of valid RSS feed items (see more about writing glob patterns for specifying which pages to include).

This function assumes, but does not verify, that all necessary feed properties are present in each document’s frontmatter. If you encounter errors, verify each page frontmatter manually.

src/pages/rss.xml.js
import rss, { pagesGlobToRssItems } from '@astrojs/rss';

export async function get(context) {
  return rss({
    title: 'Buzz’s Blog',
    description: 'A humble Astronaut’s guide to the stars',
    site: context.site,
    items: await pagesGlobToRssItems(
      import.meta.glob('./blog/*.{md,mdx}'),
    ),
  });
}
Added in: astro@1.6.14

The content key contains the full content of the post as HTML. This allows you to make your entire post content available to RSS feed readers.

When using content collections, render the post body using a standard Markdown parser like markdown-it and sanitize the result:

src/pages/rss.xml.js
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 blog = await getCollection('blog');
  return rss({
    title: 'Buzz’s Blog',
    description: 'A humble Astronaut’s guide to the stars',
    site: context.site,
    items: blog.map((post) => ({
      link: `/blog/${post.slug}/`,
      // Note: this will not process components or JSX expressions in MDX files.
      content: sanitizeHtml(parser.render(post.body)),
      ...post.data,
    })),
  });
}

When using glob imports with Markdown, we suggest using the compiledContent() helper to retrieve the rendered HTML for sanitization. Note: this feature is not supported for MDX files.

src/pages/rss.xml.js
import rss from '@astrojs/rss';
import sanitizeHtml from 'sanitize-html';

export function get(context) {
  const postImportResult = import.meta.glob('../posts/**/*.md', { eager: true }); 
  const posts = Object.values(postImportResult);
  return rss({
    title: 'Buzz’s Blog',
    description: 'A humble Astronaut’s guide to the stars',
    site: context.site,
    items: posts.map((post) => ({
      link: post.url,
      content: sanitizeHtml(post.compiledContent()),
      ...post.frontmatter,
    })),
  });
}

You can style your RSS feed for a more pleasant user experience when viewing the file in your browser.

Use the rss function’s stylesheet option to specify an absolute path to your stylesheet.

rss({
  // ex. use your stylesheet from "public/rss/styles.xsl"
  stylesheet: '/rss/styles.xsl',
  // ...
});

If you don’t have an RSS stylesheet in mind, we recommend the Pretty Feed v3 default stylesheet, which you can download from GitHub and save into your project’s public/ directory.