joshtronic

Posted in Software Development tagged JavaScript

Last modified date of Eleventy posts

I like Eleventy (11ty), but... there's always a "but", right? There have been a few things that I've struggled with. While 11ty has a ton of documentation, it's not always clear and concise. Answers on StackOverflow have been somewhat lacking. LLMs have been equally as misinformed.

One such problem I was trying to tackle is the matter of getting the last modified date from posts. There is evidently some magic under the hood when working directly with the date value, but that also changes date-based permalinks every time the post is modified.

Not ideal.

Admittedly, there very well may be a way to handle this by doing some magic with the permalink structure. Since I don't have anything additional configured for permalinks, I didn't even think about it.

Front matters

When I first approached this, I added a last modified date value to the front matter of my post, as such:

---
title: Awesomest post ever
lastmod: 2025-07-20
---

Even more awesomer content...

Note the omission of date. I don't include date in my front matter because it's derived from the filename. I've been naming my files this way for over a decade, there's no chance in hell that I want to go back and change that. Seriously, it's like 1,000 posts, and I wouldn't trust the robots to not screw things up in epic fashion.

Awesome, with the lastmod date, I should be able to grab it like I do the post's date. I did what came naturally, copied and pasted the date stuff and s/date/lastmod/ and call it a day.

No dice. I restarted 11ty, still no value coming back.

As it turns out, referencing arbitrary front matter isn't the same as accessing certain magical bits from the front matter:

This is great: {{ page.date }}
This is not: {{ page.lastmod }}

Guessing somebody had decided that they didn't want accidental overwriting of the magical stuff, thus, no ad-hoc front matter will pollute the page object.

While I never did find this documented in a way that I was able to grok, turns out you just need to drop the page and access the front matter directly:

This is great: {{ page.date }}
This is also great: {{ lastmod }}

Problem solved, next issue. This is how I'm currently doing things on my blog. I like this method because I have control over the date that is going to be shown.

I tweak posts here and there. Not everything I do warrants a last modified date. In fact, if I were to add a last modified date across all posts, it would probably impact nearly all posts on the site. I'm not convinced this is a good thing, even if "search engines like to see updated content".

Automatically add a last modified date

My own gross curiosity led me down the rabbit hole of trying to figure this out, primarily because I've yet to find a site out there that seemed to outline how to do it.

11ty has some more magic under the hood called computed data.

The gist is that you can throw some code at a collection and have it calculate things based on the post's data and front matter. This seemed perfect for adding a lastmod value to every post.

To get started, you need to create an *.11tydata.js file for your collection. I'm adding this value to my posts, so I slapped a posts.11tydata.js in my posts directory:

const fs = require('fs');

module.exports = { eleventyComputed: { lastmod: (data) => { try { // Grab the modified time from the post file const stats = fs.statSync(data.page.inputPath); const mtime = stats.mtime;

// Grab the original post date and our modified date const originalDate = new Date(data.page.date).toISOString().split('T')[0]; const modifiedDate = new Date(mtime).toISOString().split('T')[0];

// Only return the lastmod if it's different from the original date if (modifiedDate !== originalDate) { return mtime; }

return null; } catch (err) { console.error(</span><span class="token string">Error checking mtime for </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>data<span class="token punctuation">.</span>page<span class="token punctuation">.</span>inputPath<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">, err); return null; } } } };

No idea why this code block refuses to play nice :*(

Now from within your template, you can check if lastmod is there, and if so, you can use it:

{%- if lastmod -%}
    <p>Last modified: {{ lastmod | utcDate }}</p>
{%- endif -%}

Wouldn't shock me if there's some subtle timezone nonsense going on in there. My first pass was a bit bugged since the post date completely lacks a time. Since mtime has both time and date, things were thrown off by a day.

I still favor the more hands on approach, but it's nice to know that Eleventy is flexible and allows you to really do some damage with calculating data on the fly.