How to Build an Eleventy Plugin

Eleventy is an increasingly popular static site generator, thanks to the fact that it is both very customizable, and comes with a good set of defaults to let you get up and running quickly. And, most relevant to us, it also supports a simple plugin system which allows sharing customizations with others.

The heart of Eleventy's configurability lies in the optional .eleventy.js file. It is there that you can override default configuration, add additional filters to your templating language, and change just about anything else. If you don't already have one, go ahead and create it.

module.exports = (eleventyConfig) => {
};

You'll note that we are exporting a function that takes in an eleventyConfig object, and does nothing with it, leaving all the defaults in place.

Suppose that as part of our site we want to include each article author's Gravatar image. To do that, we can add a custom filter to our configuration. Let's add the skeleton of that filter.

module.exports = (eleventyConfig) => {
eleventyConfig.addFilter('gravatarUrl', () => {

});
};

Now, the way that Gravatar works is by serving up an image named after the MD5 hash of the user's email address. For example, the image url of foo@bar.com would be https://www.gravatar.com/avatar/f3ada405ce890b6f8204094deb12d8a8.

We'll need to transform the author's email address into an MD5 hash, so let's install the md5 package with npm install --dev md5. And then let's fill out the logic of the filter.

const md5 = require('md5');

module.exports = (eleventyConfig) => {
eleventyConfig.addFilter('gravatarUrl', (email) => {
const hash = md5(email.trim());
return `https://www.gravatar.com/avatar/${hash}`;
});
};

Now you'll have the gravatarUrl filter available to use anywhere in your layouts. Here is an example of using it in the Liquid templating language.

<img src="{{ authorEmail | gravatarUrl }}" />

We've got a working filter, but suppose that we're actually building a bunch of sites with Eleventy, and we're going to need this functionality again. We could just copy and paste the code everywhere. But we could also turn it into a plugin and publish it to npm so that others can easily use it.

Let's make the code change to convert it into a plugin.

const md5 = require('md5');

const gravatarPlugin = (eleventyConfig) => {
eleventyConfig.addFilter('gravatarUrl', (email) => {
const hash = md5(email.trim());
return `https://www.gravatar.com/avatar/${hash}`;
});
}

module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(gravatarPlugin);
};

You'll see that instead of directly calling addFilter in our configuration function, we define a plugin function on line 3. That function takes in the Eleventy config object and does the work of adding the filter. And then on line 11 we add the plugin. At this point all we need to do is extract the function into a separate package.

So let's create a new directory for our package. Maybe something like eleventy-plugin-gravatar. Then we'll npm init. Next we create an index.js file to copy our plugin into. Make sure that we install md5 as a dependency of our plugin package: npm install md5.

We update our new packages index.js to the following:

const md5 = require('md5');

module.exports = (eleventyConfig) => {
eleventyConfig.addFilter('gravatarUrl', (email) => {
const hash = md5(email.trim());
return `https://www.gravatar.com/avatar/${hash}`;
});
}

Then we update our .eleventy.js file to the following:

const gravatarPlugin = require('eleventy-plugin-gravatar');

module.exports = (eleventyConfig) => {
eleventyConfig.addPlugin(gravatarPlugin);
};

To test it out locally, in the plugin directory, type npm link. And then in your Eleventy site's directory, run npm link eleventy-plugin-gravatar. Start your Eleventy dev server up and you should see everything working.

At this point, all you need to do is publish the package to npm. For detailed instructions on that, see the npm documentation.

Congratulations! If you made it this far, you've created your own plugin, made it into it's own package, and maybe even published it.

Like this post? Subscribe to get the next one in your feed reader!