Skip to navigation Skip to main content
11ty Logo Sustainability Fundraising
Eleventy
Eleventy Documentation
Stable
2.0.1
Canary
3.0.0-alpha.17
Toggle Menu
Eleventy 1.93s
Gatsby 29.05s

RSS Plugin

Contents

A pack of plugins for generating an RSS (or Atom or JSON) feed using the Nunjucks templating syntax.

This plugin has a few excellent features:

Starting with RSS Plugin v2.0 and newer, there are two options to create feeds in your project using this plugin:

  1. Using a virtual template to create a feed with a few lines of configuration (easier, more abstracted).
  2. Using a manual template, adding configuration and a template file (more setup, but more control).

Installation

Available on npm.

npm install @11ty/eleventy-plugin-rss
  • v2 of this this plugin requires Eleventy v3.0 or newer.
  • v1 of this plugin is compatible with Eleventy 0.11 or newer.

Virtual Template

Pre-release only: v3.0.0-alpha.13Added in RSS 2.0.0 This method creates a feed template directly from your plugin configuration, without requiring additional files in your project.

Filename .eleventy.js
import { feedPlugin } from "@11ty/eleventy-plugin-rss";

export default function (eleventyConfig) {
eleventyConfig.addPlugin(feedPlugin, {
type: "atom", // or "rss", "json"
outputPath: "/feed.xml",
collection: {
name: "posts", // iterate over `collections.posts`
limit: 10, // 0 means no limit
},
metadata: {
language: "en",
title: "Blog Title",
subtitle: "This is a longer description about your blog.",
base: "https://example.com/",
author: {
name: "Your Name",
email: "", // Optional
}
}
});
};
Filename .eleventy.js
const { feedPlugin } = require("@11ty/eleventy-plugin-rss");

// If you already have a configuration file make sure you don’t end
// up with multiple `module.exports =` in the same file!
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(feedPlugin, {
type: "atom", // or "rss", "json"
outputPath: "/feed.xml",
collection: {
name: "posts", // iterate over `collections.posts`
limit: 10, // 0 means no limit
},
metadata: {
language: "en",
title: "Blog Title",
subtitle: "This is a longer description about your blog.",
base: "https://example.com/",
author: {
name: "Your Name",
email: "", // Optional
}
}
});
};

This configuration is the only step you need. If you need additional control over the template output, you can use the Manual Template method.

Expand for full options list
  • type: (required) One of "atom" (default), "rss", or "json"
  • outputPath: (required, default: /feed.xml) Where to write the template in the output directory.
  • inputPath: (optional, default based on metadata.title) Change where the virtual template pretends to live on the file system (e.g. if you want project directory data files to apply via the Data Cascade)
  • collection.name: Collection entries to iterate over to populate your feed (e.g. name: "posts" for collections.posts)
  • collection.limit: Number of entries to include (0 means no limit).
  • metadata: Content used to populate the feed boilerplate.
  • stylesheet: URL to an XSL stylesheet to change how the feed is rendered in the browser (only for Atom and RSS feeds).
  • templateData, defaults to {}: Additional data to apply to the template (e.g. to add your feed to the Navigation plugin)

Manual Template

Configuration

Open up your Eleventy config file (probably .eleventy.js) and use addPlugin:

Filename .eleventy.js
import pluginRss from "@11ty/eleventy-plugin-rss";

export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss);
};
Filename .eleventy.js
const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss);
};
INFO:
You’re only allowed one module.exports in your configuration file, so make sure you only copy the require and the addPlugin lines above!
Expand to see full options list

Added in RSS 1.1.0 Advanced control of PostHTML rendering options via posthtmlRenderOptions.

const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss, {
posthtmlRenderOptions: {
closingSingleTag: "default", // opt-out of <img/>-style XHTML single tags
},
});
};

Supplies the following Nunjucks Filters

  • getNewestCollectionItemDate: Gets the most recently updated content in the collection. Use with dateToRfc3339 to properly format the Date for the top-level <updated> element. Added in RSS 1.1.0
  • dateToRfc3339: format a Date for use in a <entry><updated> element. (Atom feeds) Added in RSS 1.1.0
  • dateToRfc822: format a Date for use in a <pubDate> element. (RSS feeds) Added in RSS 1.2.0

Less Important Filters

  • Deprecated absoluteUrl: For performance reasons, the renderTransforms filter is recommended instead, making use of the HTML <base> plugin. converts a single URL (relative or absolute path) to a full absolute URL including protocol, domain, full path.
  • Deprecated htmlToAbsoluteUrls: For performance reasons, the renderTransforms filter is recommended instead, making use of the HTML <base> plugin. (async) transforms all of the URLs in a block of HTML with absoluteUrl above. Uses posthtml-urls with a[href], video[src], audio[src], source, img[src], [srcset] and a whole bunch more.
  • ⚠️ Removed in RSS v2.0.0 rssLastUpdatedDate, poorly named (works with Atom and JSON feeds, not RSS). Use getNewestCollectionItemDate | dateToRfc3339 instead.
  • ⚠️ Removed in RSS v2.0.0 rssDate, poorly named (works with Atom and JSON feeds, not RSS). Use dateToRfc3339 instead.

Use with other template languages

Added in RSS 1.1.0 This plugin exports dateToRfc3339, dateToRfc822 (Added in RSS 1.2.0), getNewestCollectionItemDate, absoluteUrl, and convertHtmlToAbsoluteUrls functions so you can use with your own filters. For example:

const pluginRss = require("@11ty/eleventy-plugin-rss");

module.exports = function (eleventyConfig) {
eleventyConfig.addLiquidFilter("dateToRfc3339", pluginRss.dateToRfc3339);

// New in RSS 1.2.0
eleventyConfig.addLiquidFilter("dateToRfc822", pluginRss.dateToRfc822);
};
INFO:
Do keep in mind that escaping HTML content is a feature provided as part of Nunjucks. Moving to another template language may require a different option for escaping (for example, html-entities).

Sample Feed templates

Copy and paste this template and modify the JSON metadata to match your feed’s needs. Make sure collections.posts matches the template collection you want to provide a feed for.

INFO:
The following feed samples require RSS Plugin v2.0 or newer. Samples for RSS Plugin v1 are available on older versions of the docs.

---json
{
"permalink": "feed.xml",
"eleventyExcludeFromCollections": true,
"metadata": {
"title": "My Blog about Boats",
"description": "I am writing about my experiences as a naval navel-gazer.",
"language": "en",
"base": "https://example.com/",
"author": {
"name": "Boaty McBoatFace"
}
}
}
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="{{ metadata.language or page.lang }}">
<title>{{ metadata.title }}</title>
<subtitle>{{ metadata.description }}</subtitle>
<link href="{{ permalink | htmlBaseUrl(metadata.base) }}" rel="self" />
<link href="{{ metadata.base | addPathPrefixToFullUrl }}" />
<updated>{{ collections.posts | getNewestCollectionItemDate | dateToRfc3339 }}</updated>
<id>{{ metadata.base | addPathPrefixToFullUrl }}</id>
<author>
<name>{{ metadata.author.name }}</name>
</author>
{%- for post in collections.posts | reverse %}
{%- set absolutePostUrl %}{{ post.url | htmlBaseUrl(metadata.base) }}{% endset %}
<entry>
<title>{{ post.data.title }}</title>
<link href="{{ absolutePostUrl }}" />
<updated>{{ post.date | dateToRfc3339 }}</updated>
<id>{{ absolutePostUrl }}</id>
<content type="html">{{ post.content | renderTransforms(post.data.page, metadata.base) }}</content>
</entry>
{%- endfor %}
</feed>
---json
{
"permalink": "feed.xml",
"eleventyExcludeFromCollections": true,
"metadata": {
"title": "My Blog about Boats",
"description": "I am writing about my experiences as a naval navel-gazer.",
"language": "en",
"base": "https://example.com/",
"author": {
"name": "Boaty McBoatFace"
}
}
}
---
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="{{ metadata.base | addPathPrefixToFullUrl }}" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ metadata.title }}</title>
<link>{{ metadata.base | addPathPrefixToFullUrl }}</link>
<atom:link href="{{ permalink | htmlBaseUrl(metadata.base) }}" rel="self" type="application/rss+xml" />
<description>{{ metadata.description }}</description>
<language>{{ metadata.language or page.lang }}</language>
{%- for post in collections.posts | reverse %}
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.base) %}
<item>
<title>{{ post.data.title }}</title>
<link>{{ absolutePostUrl }}</link>
<description>{{ post.content | renderTransforms(post.data.page, metadata.base) }}</description>
<pubDate>{{ post.date | dateToRfc822 }}</pubDate>
<dc:creator>{{ metadata.author.name }}</dc:creator>
<guid>{{ absolutePostUrl }}</guid>
</item>
{%- endfor %}
</channel>
</rss>
---json
{
"permalink": "feed.json",
"eleventyExcludeFromCollections": true,
"metadata": {
"title": "My Blog about Boats",
"description": "I am writing about my experiences as a naval navel-gazer.",
"language": "en",
"base": "https://example.com/",
"author": {
"name": "Boaty McBoatFace"
}
}
}
---
{
"version": "https://jsonfeed.org/version/1.1",
"title": "{{ metadata.title }}",
"language": "{{ metadata.language or page.lang }}",
"home_page_url": "{{ metadata.base | addPathPrefixToFullUrl }}",
"feed_url": "{{ permalink | htmlBaseUrl(metadata.base) }}",
"description": "{{ metadata.description }}",
"authors": [
{
"name": "{{ metadata.author.name }}"
}
],
"items": [
{%- for post in collections.posts | reverse %}
{%- set absolutePostUrl %}{{ post.url | htmlBaseUrl(metadata.base) }}{% endset %}
{
"id": "{{ absolutePostUrl }}",
"url": "{{ absolutePostUrl }}",
"title": "{{ post.data.title }}",
"content_html": {% if post.content %}{{ post.content | renderTransforms(post.data.page, metadata.base) | dump | safe }}{% else %}""{% endif %},
"date_published": "{{ post.date | dateToRfc3339 }}"
}
{% if not loop.last %},{% endif %}
{%- endfor %}
]
}

Place the file in your input directory (and give it a .njk extension). For example: src/feed.njk or src/feed.json. If your input directory is src, the file will be transformed into a feed.xml (or feed.json if you’re using the JSON variant) file at the root of your website when Eleventy builds. It can then be useful to check the file against a feed validator, such as the W3C Feed Validation Service to make sure that the output was good.

Ultimately your feed will be available at https://yourwebsite.com/feed.xml (or https://yourwebsite.com/feed.json)

Community Plugins


Other pages in Official Plugins: