Add an 'Old Content' warning in Eleventy

Posted

I recently lamented how frustrating it is when articles omit the published date. Things move fast in the tech industry! Even articles that are 6-12 months old can be out of date by the time you read them.

Aaron Powell retweeted that he'd added a step to his blog build engine to include a warning if the post was more than three years old. Brilliant!

Not only does he have the date for those that care to look, but he also has a banner that catches people's attention and keeps them from going down a no-longer-relevant rabbit hole.

Ulterior motives

Another reason I thought this was such a great idea is because I'm not a frequent blogger.

I write a couple posts and then disappear into the ether for a couple years until I get the motivation to write a couple more. (The fact my last post was 18 months ago should be case in point).

I don't want to delete old posts, but some of them are from when I was a code newbie. I don't really want prospective employers landing on one of them and assuming they're reflective of my current skills or knowledge.

So on a rainy Sunday afternoon I got to work.

Eleventy content dates

This blog is built with a simple site generator called Eleventy. It's written in JavaScript, and gives you freedom to choose your templating language (I like nunjucks).

The first thing I did was open up the Eleventy docs for working with dates. There were a number of date values available to templates including created, Last Modified and the date added by front matter.

Sometimes I go back and fix a stray typo on old posts, so I didn’t want to use the Last Modified date. And sometimes I write a post long before I actually publish it which ruled out created. This left using the front matter date as making the most sense.

I added a dump of the date object to a template to see what I was working with.

post.njk

{{ date | dump }}
//  returns "2022-06-23T00:00:00.000Z"
 
{{ date }}
// returns Thu Jun 23 2022 08:00:00 GMT+0800 (Australian Western Standard Time)


I could see that dates default to midnight UTC, and calling the date within the template automatically converted it to a string. Comparing their raw date object with a regular JavaScript date object should be simple.

Eleventy uses wrapper for JavaScript dates and times called Luxon. (Similar to Moment.js, but lighter and still actively maintained).

I scanned through Luxon's docs to see if they had any built-in methods that could take two dates and return the difference between them. DiffNow was better than that, because it only took one date and compared it the date the function was called.

We can't write our function inside a nunjucks template, so where do we add the code?

Eleventy shortcodes

Eleventy enables you to create and use shortcodes. These are like shortcuts you can add to your template (or markdown) that will call your JavaScript function and returns a value.

Shortcodes are added to your Eleventy config file (eleventy.js). You can house the entire shortcode function in your config file, or you can import it from another file. I prefer to reference filters and shortcodes, while keeping the actual code separated into their own files.

I also like to do my 'setup' first, so I added the shortcode reference to the config before I actually created it. In the example below, "oldContentWarning" is the name of shortcode file, and the second part is the path to that file from the root folder.

eleventy.js

module.exports = function (config) {
    // other config stuff here

    config.addShortcode(
        'oldContentWarning',
        require('./src/utils/shortcodes/oldContentWarning.js')
    );

    // other config stuff here
};

I then created my shortcode folder and new oldContentWarning.js file.

I started by importing the DateTime module from Luxon and adding a brief description of the function for future reference.

oldContentWarning.js

const {DateTime} = require('luxon');
 
// show a warning if the number of months
// between today and the passed in date object
// exceeds allowed timeframe


I then wrote a module that would take the front matter date as an argument and determine how many months there were between that date and now.

If the difference was more than 24 months, it would return some HTML warning the user the content was old. If the difference was less than 24 months, it would just bail out and return null.

oldContentWarning.js

module.exports = (date) => {
  let dateToISO = DateTime.fromJSDate(date);
  let difference = dateToISO.diffNow('months').toObject();
 
  if (difference.months < -24) {
    return `<p class="warning--lg">
        This post is over two years old, the content may be out of date.
    </p>`;
  } else {
    return null;
  }
};

It turns out returning null (or simply returning) as I do in ReactLand does not work here.

Shortcodes must return something.

I changed null to an empty string and it worked.

Here's the full code:

oldContentWarning.js

const {DateTime} = require('luxon');
 
// show a warning if the number of months
// between today and the passed in date object
// exceeds allowed timeframe
 
module.exports = (date) => {
  let dateToISO = DateTime.fromJSDate(date);
  let difference = dateToISO.diffNow('months').toObject();
 
  if (difference.months < -24) {
    return `<p class="warning--lg">
        This post is over two years old, the content may be out of date.
    </p>`;
  } else {
    return ``;
  }
};

Usage

Using the shortcode within my nunjucks template was simple. (Shortcodes can also be added directly to markdown files).

post.njk

{% oldContentWarning page.date %}

I added a touch of styling, and voila`!

See it in action.

Known limitations

The date comparison takes place at build time because the website is statically generated. This means the difference in time calculated will be off by however long it's been since I triggered the last build.

My posting is sporadic, so sometimes a post could be more than 2 years old without the warning. But even with this limitation it suits my use case - so I'm happy!

Jess Budd headshot

Jess is a senior software engineer and web accessibility nerd. When she’s not writing, speaking or tweeting about tech, you’ll find her putting together lego or going on walks with her doggo.