Home

Local links in Eleventy, Part 2

2024-02-14

Background

The only thing I didn't like about Eleventy when I started using it was that local Markdown links, like /posts/my-post.md wasn't automatically transformed into their rendered URL counterparts, like /posts/my-post/. Having links pointing to the source files allows you to follow them locally when working with the content, and many Markdown editors can both help autocomplete links as you type as well as highlight any broken ones. For me, however, the most important benefit of working this way is that the content can remain unaware of the output format, so to speak. The less site details there are in the content, the more portable that content will be.

A while back I wrote a post about how to maintain working local links in Eleventy, and have them automatically transformed into the correct corresponding URLs at build-time. After publishing that post, I got a comment from Eleventy author Zach Leatherman, acknowledging that the current behavior isn't optimal, and that the issue would be solved in Eleventy 3.0.0. Delivering on that promise, Zach has now introduced the updated behavior as part of Eleventy 3.0.0-alpha5, yay! If you're ready to jump aboard the 3.0.0 train, here are some good, official directions to follow.

New times

My own solution to this problem was to implement an Eleventy Transform that replaced all local paths in links with rendered URLs. The official solution comes in two parts, a plugin and a filter, and the plugin uses a similar approach to mine. It's always nice to see you've gotten something right as a beginner, so that felt validating!

The plugin

The new Eleventy behavior comes as a bundled plugin called InputPath to URL that is optional and turned off by default. It can be enabled with a couple of lines in .eleventy.js:

import { InputPathToUrlTransformPlugin } from "@11ty/eleventy";

export default function(eleventyConfig) {
  eleventyConfig.addPlugin(InputPathToUrlTransformPlugin);
  
  // Further configuration ...
};

Once activated, the plugin will replace all references to local paths with their URL counterparts. My own link transformer only dealt with a[href], but the InputPath to URL plugin also transforms audio[src], img[src], [srcset] and a few more.

The filter

In addition to the above plugin, the new Eleventy release provides a filter called inputPathToUrl, that offers the same URL-remapping functionality. Here’s a Nunjucks example:

<a href="{{ "/posts/my-post.md" | inputPathToUrl }}">My post</a>

The above will be rendered as:

<a href="/posts/my-post/">My post</a>

Conclusion

I think my own link transformer turned out pretty good, but it’s still a relief to remove custom code in favor of a common solution. Packaging the functionality as a plugin is tidier than explicitly configuring a transform, which I previously did. The next time I want to customize something in Eleventy, I’ll probably use that as an excuse to try implementing a plugin of my own.

I’m very grateful that Zach picked up this old issue, Eleventy just keeps getting better and better. I can also happily report that the migration of this site to Eleventy 3.0.0 required only very minor changes. Check out the plan for the 3.0.0 release for more details about what’s included.

And lastly, if you want to read more about Eleventy, I've created a page with all my Eleventy posts, so that you can follow along on my adventures.

Happy blogging!