- Stable
3.0.0
Toggle Menu
5.81s
43.36s
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:
- 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 transform,
<base>
, InputPath to URL etc.) If you’re using a--pathprefix
in your project, the URLs in your feed content are normalized for you.
Starting with RSS Plugin v2.0 and newer, there are two options to create feeds in your project using this plugin:
- Using a virtual template to create a feed with a few lines of configuration (easier, more abstracted).
- 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
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. 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 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 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 (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.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 withdateToRfc3339
to 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, therenderTransforms
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, therenderTransforms
filter is recommended instead, making use of the HTML<base>
plugin. (async) transforms all of the URLs in a block of HTML withabsoluteUrl
above. 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 | dateToRfc3339
instead. - ⚠️ Removed in RSS v2.0.0
rssDate
, poorly named (works with Atom and JSON feeds, not RSS). UsedateToRfc3339
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:
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-plugin
for Liquid.