RSS Plugin
On this page
A pack of plugins for generating an RSS (or Atom or JSON) feed using the Nunjucks templating syntax.
Feature highlights
- URLs are normalized to absolute URLs, pointing to your hosted domain for maximum feed reader compatibility. Read more about the dangers of relative URLs in your feeds on CSS Tricks (Related: #36).
- Existing project Transforms are applied to feed entries (e.g. Image HTML Transform,
<base>, InputPath to URL, etc.) If you’re using a--pathprefixin your project, the URLs in your feed content are normalized for you.
Since RSS Plugin v2.0, this plugin offers two options to create feeds in your project:
- Virtual templates let you create a feed with a few lines of configuration. (This is easier, more abstracted.)
- Manual templates need more configuration and a template file. (This requires more setup, but offers more control.)
Installation
Available on npm.
npm install @11ty/eleventy-plugin-rss
v2of this this plugin requires Eleventy v3.0 or newer.v1of this plugin is compatible with Eleventy 0.11 or newer.
Virtual Template
Added in v3.0.0Added in RSS 2.0.0 This method creates a feed template directly from your plugin configuration, without requiring additional files in your project. The default template uses Nunjucks, so make sure njk is included templateFormats in your Eleventy config. Read more about Virtual Templates.
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
}
}
});
};
const { feedPlugin } = require("@11ty/eleventy-plugin-rss");
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 for the Virtual Template method. 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 onmetadata.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"forcollections.posts)collection.limit: Number of entries to include. (Use0for 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.config.js) and use addPlugin:
import pluginRss from "@11ty/eleventy-plugin-rss";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss);
};
const pluginRss = require("@11ty/eleventy-plugin-rss");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss);
};
Expand to see full options list
Added in RSS 1.1.0 Advanced control of PostHTML rendering options via posthtmlRenderOptions.
import pluginRss from "@11ty/eleventy-plugin-rss";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginRss, {
posthtmlRenderOptions: {
closingSingleTag: "default", // opt-out of <img/>-style XHTML single tags
},
});
};
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 withdateToRfc3339to properly format the Date for the top-level<updated>element. Added in RSS 1.1.0dateToRfc3339: format a Date for use in a<entry><updated>element. (Atom feeds) Added in RSS 1.1.0dateToRfc822: 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, therenderTransformsfilter 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, therenderTransformsfilter is recommended instead, making use of the HTML<base>plugin. (async) Transforms all of the URLs in a block of HTML withabsoluteUrlabove. Uses posthtml-urls witha[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). UsegetNewestCollectionItemDate | dateToRfc3339instead. - ⚠️ Removed in RSS v2.0.0
rssDate, poorly named (works with Atom and JSON feeds, not RSS). UsedateToRfc3339instead.
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:
import pluginRss from "@11ty/eleventy-plugin-rss";
export default function (eleventyConfig) {
eleventyConfig.addLiquidFilter("dateToRfc3339", pluginRss.dateToRfc3339);
// New in RSS 1.2.0
eleventyConfig.addLiquidFilter("dateToRfc822", pluginRss.dateToRfc822);
};
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);
};
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.
---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
eleventy-xml-pluginfor Liquid.