Extend 11ty: Implement Jekyll’s post_url tag as a shortcode.

A quick guide showing how to write a post_url shortcode for 11ty, similar to Jekyll's out-of-the-box post_url tag.

I prefer and rely on my Static Site Generator to figure out what the correct and up to date permalink to a post is. I do this as a means to:

  • protect myself automatically against any future changes in my blog’s permalink structure, by not needing to manually edit my posts and update each link,
  • catch any broken links before they make it to production, and,
  • reap a small benefit of one less HTTP request.

If you happen to change your permalink structure, you’ll be configuring a HTTP 301 redirect on the server regardless. However, I believe using a helper tag is a cleaner solution for links within your domain.

Why did I end up writing this shortcode?

I recently moved from Jekyll to 11ty for various reasons, chief among them the desire to move from two ecosystems, Ruby and JavaScript, to just JavaScript. It allows me to add new functionality with ease. Additionally, working with and debugging in a single asset pipeline is easier.

Jekyll offers a custom liquid tag, post_url (see here). 11ty does not have this shortcode. However, it’s easy to extend the framework.

In your .eleventy.js file, 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 sanity checks on the collection and slug arguments passed in. An error will be thrown in case the collection is empty, or invalid, or if the slug passed in is not a string, or if no file is found with the provided slug.

Use the shortcode as follows in your blog posts. I use Shopify’s liquid, so for me it looks like:

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

On my blog, it generates:


If you’re in the process of migrating away from Jekyll, this would allow you to modify your files as little as possible. You can use RegEx to simply add the collection name where post_url tag has been used earlier.

You can also pass this result to a custom filter that converts it to an absolute URL. If you’d like to see how I have implemented this filter, do let me know!

Added flexibility – use any collection!

One apparent advantage of specifying the collection to use is you’re not just limited to generating links to your blog posts. You can do so for any collection – notes, projects, and so on, and on any page that your templating engine will process.

If this is a use-case for you, you might also wish to rename the shortcode to something more appropriate.


Comment via email.