I preĀ­fer and rely on my Static Site Generator to ļ¬gĀ­ure out what the corĀ­rect and up to date permaĀ­link to a post is. I do this as a means to:

  • proĀ­tect myĀ­self auĀ­toĀ­matĀ­iĀ­cally against any fuĀ­ture changes in my blogā€™s permaĀ­link strucĀ­ture, by not needĀ­ing to manĀ­uĀ­ally edit my posts and upĀ­date each link,
  • catch any broĀ­ken links beĀ­fore they make it to proĀ­ducĀ­tion, and,
  • reap a small benĀ­eĀ­ļ¬t of one less HTTP reĀ­quest.

If you hapĀ­pen to change your permaĀ­link strucĀ­ture, youā€™ll be conĀ­ļ¬gĀ­urĀ­ing a HTTP 301 rediĀ­rect on the server reĀ­gardĀ­less. However, I beĀ­lieve usĀ­ing a helper tag is a cleaner soĀ­luĀ­tion for links within your doĀ­main.

Why did I end up writĀ­ing this shortĀ­code?

I reĀ­cently moved from Jekyll to 11ty for varĀ­iĀ­ous reaĀ­sons, chief among them the deĀ­sire to move from two ecosysĀ­tems, Ruby and JavaScript, to just JavaScript. It alĀ­lows me to add new funcĀ­tionĀ­alĀ­ity with ease. Additionally, workĀ­ing with and deĀ­bugĀ­ging in a sinĀ­gle asĀ­set pipeline is easĀ­ier.

Jekyll ofĀ­fers a cusĀ­tom liqĀ­uid tag, post_url (see here). 11ty does not have this shortĀ­code. However, itā€™s easy to exĀ­tend the frameĀ­work.

In your .eleventy.js ļ¬le, add:

module.exports = function(config11ty) {
config11ty.addShortcode("post_url", (collection, slug) => {
try {
if (collection.length < 1) throw "Collection appears to be empty";
if (!Array.isArray(collection))
throw "Collection is an invalid type - it must be an array!";
if (typeof slug !== "string")
throw "Slug is an invalid type - it must be a string!";

const found = collection.find(p => p.fileSlug.includes(slug));
if (found === 0 || found === undefined)
throw `${slug} not found in specified collection.`;
else return found.url;
} catch (e) {
`An error occured while searching for the url to ${slug}. Details:`,

We have a few sanĀ­ity checks on the collection and slug arĀ­guĀ­ments passed in. An erĀ­ror will be thrown in case the colĀ­lecĀ­tion is empty, or inĀ­valid, or if the slug passed in is not a string, or if no ļ¬le is found with the proĀ­vided slug.

Use the shortĀ­code as folĀ­lows in your blog posts. I use Shopifyā€™s liqĀ­uid, so for me it looks like:

{% post_url collections.articles, 'check-string-in-array-liquid-vs-nunjucks' %}

On my blog, it genĀ­erĀ­ates:


If youā€™re in the process of miĀ­gratĀ­ing away from Jekyll, this would alĀ­low you to modĀ­ify your ļ¬les as litĀ­tle as posĀ­siĀ­ble. You can use RegEx to simĀ­ply add the colĀ­lecĀ­tion name where post_url tag has been used earĀ­lier.

You can also pass this reĀ­sult to a cusĀ­tom ļ¬lĀ­ter that conĀ­verts it to an abĀ­solute URL. If youā€™d like to see how I have imĀ­pleĀ­mented this ļ¬lĀ­ter, do let me know!

Added ļ¬‚exĀ­iĀ­bilĀ­ity - use any colĀ­lecĀ­tion!

One apĀ­parĀ­ent adĀ­vanĀ­tage of specĀ­iĀ­fyĀ­ing the colĀ­lecĀ­tion to use is youā€™re not just limĀ­ited to genĀ­erĀ­atĀ­ing links to your blog posts. You can do so for any colĀ­lecĀ­tion - notes, proĀ­jects, and so on, and on any page that your temĀ­platĀ­ing enĀ­gine will process.

If this is a use-case for you, you might also wish to reĀ­name the shortĀ­code to someĀ­thing more apĀ­proĀ­priĀ­ate.