Skip to content

Fix dates on Eleventy RSS feeds

The official way to generate RSS feed in Eleventy is to use filters from eleventy-plugin-rss plugin. The sample RSS template from the plugin’s documentation is a good starter. I use the same code to generate RSS feeds on my website.

The RSS feeds made by the official method has one problem, <updated> fields use date from the page object. The date don’t change when you make any changes to the content. RSS feed readers rely on <updated> fields to pick up any changes in the post since it is originally published.

Screengrab of feedbin.com showing changes since original
The RSS reader, Feedbin.com highlights changes since original.

The Eleventy provides Last Modified function for the date field, but you’ll lose out on the fixed creation date or published date. Moreover, last modified date is unreliable like creation date on CI environments.

Git commit time

The creator of the Eleventy, Zach, suggests Git commit time as a reliable time to use as modified or last updated time. It will stay the same across machines. This is the approach I’m going to use to fix the dates on the RSS feed.

I have created a plugin eleventy-plugin-git-commit-date, to get Git commit time from a file path. The plugin also provide a template filter to get the latest Git commit time from a collection.

RSS feed with Git commit time

First, you need to install the plugin, npm install --save eleventy-plugin-git-commit-date. This plugin is a companion to the official eleventy-plugin-rss plugin. So, if you haven’t installed RSS plugin, you have to install and enable that too.

Next, enable the plugin in .eleventy.js.

// .eleventy.js
const pluginGitCommitDate = require("eleventy-plugin-git-commit-date");

module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginGitCommitDate);
};

Now, you should be able to access filters getGitCommitDateFromPath and getCollectionNewestGitCommitDate in your templates.

Firstly, let’s create a data file, src/_data/config.js with these contents.

// src/_data/config.js
module.exports = {
now: new Date(),
};

The data now will have the time at which you run eleventy. This will come handy later.

Now, update your feed template using filters from the plugin

---json
{
"permalink": "feed.xml",
"eleventyExcludeFromCollections": true,
"metadata": {
"title": "My Blog about Boats",
"subtitle": "I am writing about my experiences as a naval navel-gazer.",
"url": "https://example.com/",
"feedUrl": "https://example.com/feed.xml",
"author": {
"name": "Boaty McBoatFace",
"email": "[email protected]"
}
}
}
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ metadata.title }}</title>
<subtitle>{{ metadata.subtitle }}</subtitle>
<link href="{{ metadata.feedUrl }}" rel="self"/>
<link href="{{ metadata.url }}"/>
- <updated>{{ collections.posts | getNewestCollectionItemDate | dateToRfc3339 }}</updated>
+ <updated>{{ collections.posts | getCollectionNewestGitCommitDate | default(config.now) | dateToRfc3339 }}</updated>
<id>{{ metadata.url }}</id>
<author>
<name>{{ metadata.author.name }}</name>
<email>{{ metadata.author.email }}</email>
</author>
{%- for post in collections.posts %}
{% set absolutePostUrl %}{{ post.url | url | absoluteUrl(metadata.url) }}{% endset %}
<entry>
<title>{{ post.data.title }}</title>
<link href="{{ absolutePostUrl }}"/>
- <updated>{{ post.date | dateToRfc3339 }}</updated>
+ <updated>{{ post.inputPath | getGitCommitDateFromPath | default(post.date) | dateToRfc3339 }}</updated>
<id>{{ absolutePostUrl }}</id>
<content type="html">{{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}</content>
</entry>
{%- endfor %}
</feed>

You need to update the two <updated> fields. The first <updated> is for the whole feed. Here, we need to populate the Git commit date from the recently committed file from the collection. getCollectionNewestGitCommitDate returns Git commit date of recently committed file. In case, you haven’t committed any posts to Git, this filter will return undefined. The default will return the provided value in case the value before the filter is undefined. When prior filter to default(config.now) return undefined will return config.now which is the current time. Lastly, we use dateToRfc3339 from Eleventy RSS plugin to format the date.

The second <updated> field is for each post. In case the current post file is not committed to Git, the getGitCommitDateFromPath returns undefined. So, to handle that case, we are using default(post.date) to populate with date from the file or front-matter.

That’s all you need to do to fix dates in the RSS feeds.

I’m available for new projects from October 2021.

Get in touch