Eleventy Static Site Generator From WordPress

Learn how to create your WordPress website as a static website using eleventy and WPGraphQL

eleventy wordpress graphql
Reading Time: 8 minutes

In some circles, static site generators have become all the rage. I don’t need to go into details about why they’re better than dynamically generated sites – this article isn’t to preach to you about the benefits or drawbacks of such a system as I’m sure you’ll have already done your research and decided that you want to use WordPress as a headless CMS with Eleventy to generate the pages for you.

If you don’t know what I am talking about, you can check out Eleventy here. You can check out the benefits and drawbacks of WordPress as a Headless CMS here.

Eleventy Static Site Generator From WordPress GraphQL

Every option I saw for using WordPress as your content management system with Eleventy as the static site generator used the WordPress REST API to do it. I don’t really know why, but I wanted to use GraphQL. It looks and feels cleaner to me for some reason. Perhaps it’s because I’d initially invested a few hours (heh) into researching using Gatsby as the SSG with WP backend. Gatsby uses GraphQL so it seemed logical.

And even with the REST API in use, there’s really no fully out of the box solution for setting up WordPress as a headless CMS with Eleventy static site generation. Well now there is. I’ve developed a full Eleventy static site generator from WordPress and you can find it at https://github.com/most-useful/11ty-wordpress-graphql – but you will still need to be familiar with some concepts of building websites. It’s not going to hold your hand in quite the same way as WordPress alone will.

I’ve tried to make it as intuitive as I can, but as I got more into it I discovered I’d like it to do lots of things, because ultimately I want my entire site replicated into static html. So it has a lot of what might be considered bloat. You can choose whether to use it or not 🙂

How To Use My 11ty Static Site Generator From WordPress GraphQL

Firstly, if you’re not familiar with Eleventy, this is probably not the project to be getting yourself familiar with it. There’s a lot of additional cruft and you’d be well advised to watch Learning with Jason where he goes over how to start from absolutely scratch with Eleventy and has mentorship from Zach Leatherman, the creator of 11ty to help him through it.

Install WPGraphQL

In order to get GraphQL data from WordPress you’ll need to install the WPGraphQL plugin into WordPress. The best way to do that is through the plugins dashboard in WordPress. Search for WPGraphQL. The icon for the recommended plugin looks a bit like an elephant and the plugin is developed by WPGraphQL. At the time of writing it looks like the image below;

WPGraphQL Plugin screenshot
WPGraphQL plugin appearance as at 24 April 2021

There are some configuration options for WPGraphQL but you don’t need to change anything from the default so I won’t go into them.

Add authorGravatarURL plugin to WordPress

The default WPGraphQL schema doesn’t include a way to get comment author’s Gravatar URL out when you’re not logged in to the GraphQL session. Given that this information is publicly available on a normal WordPress site I decided I’d like to keep Gravatars on my static site, since the comments are sourced from WordPress.

Note that you can calculate the Gravatar URL if you have access to the commenters e-mail address. But from the public WPGraphQL you don’t have access to that data – nor should you. But the Gravatar URL is a hash of that email address and reveals nothing about the commenter.

So I created a plugin to add the Gravatar URL. You’ll need to download it from https://github.com/most-useful/wp-graphql-comments-gravatar and I recommend downloading the release version as a ZIP file so you can upload it straight to your WordPress plugin dashboard. The source code is of course available on Github if you want to make sure there’s nothing untoward going on.

This will then present authorGravatarURL under the comments schema for WPGraphQL responses requesting comments. Which I do in the posts.js data file. If you don’t want WordPress comments you could edit the file src/_data/posts.js to remove that portion of the code and not bother installing this plugin.

There is nothing to configure for this plugin either.

Check in the GraphQL IDE on WordPress to make sure the authorGravatarUrl is exposed under the comments schema.

Download The 11ty-WordPress-GraphQL package from Github

You can use git clone or fork the repository to download the package on to your own computer and begin working with it.

git clone git@github.com:most-useful/11ty-wordpress-graphql.git

A README.md file is included with the project which will give you a good head start on where you absolutely need to modify in order to get things working. Give it a quick read. There’s some additional extras included in the package aside from the templates and data drivers.

Edit config.json

Various pieces of information need to be set in config.json. A demonstration file is included in the repository named demo-config.json. You can copy that one if you like to give you a good starting point. I’ll explain the different parts;

  • imgSource – The package will automatically download and optimise your WordPress posts featured images – and will generate 3 types of image files for modern browsers. This is done using the 11ty-image plugin if you want more detailed information about what that will do. But, it will only automatically grab featured images. In many cases you may have images embedded in your articles and stored in the WordPress media library. This configuration option lets you specify where you want images to be downloaded and stored locally from. Normally this would be the same as your website address. If you think you may have embedded images that use the non-www prefix as well as the www prefix you’ll have to create two separate entries. This configuration option is an array of strings.
  • graphqlUrl – This is the WPGraphQL endpoint address. It’ll likely be https://www.yourdomain.com/?graphql – this config option is a string
  • urlRewriterUrls – This is similar in a way to the imgSource configuration option and you may find that the URLs are in fact the same in both. I’ve kept them as separate options as they might not always be. It’s necessary because when you create a link in a page or post in WordPress to another page or post, the full URL is stored inside the article. In 11ty-wordpress-graphql I change that philosophy to use relative URLs which means you can host your new static site anywhere you like without worrying about broken internal links.

    But, to do this, you need to tell the system where your original links were so it can rewrite them to relative URLs. Also, bear in mind that this isn’t as intelligent as it sounds. All it does is strip the scheme and host details from the URL. The rest of the ‘permalink’ is left alone. This means that your permalink structure in WordPress must match your Eleventy permalink structure that you specify in the templates front matter.

    This setting is an array of strings, very similar to the imgSource
  • useCache – The data providers will use the 11ty caching system to cache the WPGraphQL responses if this is set to true. If you’re not changing the WordPress side of things (or editing the data provider logic) this is a good idea. For example, you’ll probably want to modify the HTML that’s derived by 11ty. I hope you do anyway. But while you’re testing you don’t need to keep hitting your WPGraphQL endpoint every time you make a change to your template files, so they’re cached if this is set to true.
  • useMatomo – I use Matomo for analytics and have included the Matomo default script in layout.njk. If you don’t use Matomo, set this to false or remove the Matomo code from layout.njk
  • matomoUrl – this is so Matomo script knows where your Matomo server is
  • useGoogleAnalytics – GA code is included in layout.njk too, and the googleAnalyticsCode will be automatically generated if this is true. Do note that this is Google Analytics V3 code though – I haven’t looked at V4 because I don’t use it. Yet.
  • googleAnalyticsCode – this is your site code for GA
  • ignoreEmbeddedImages – this will tell the package not to do anything with your embedded images specified in imgSource. They’ll not be downloaded or rewritten and will be left in the original Media Library. This might be useful if, for some reason, you wanted to continue hosting images through WordPress but have static HTML for the main posts.

I told you up front it was bloated didn’t I? 🙂

Edit autoinject.json

The autoinject.json controls automatically injected HTML code or script which is added to your templates after processing. I’ve done this to mimick the very excellent AdInserter plugin that’s available for WordPress. My version is significantly limited compared to the WP version, but it suffices my needs.

As you can see from the demo file – which you’ll need to rename from demo-autoinject.json to just autoinject.json – you can specify any number of places to autoinject script or html. I’ll go through what each part means;

  • tag – this is an HTML element to look for in the generated file. It can be any valid DOM element as it’ll be passed to JSDOM for processing. This means it can also contain class or id attributes.

    For example, to look for every H2 in the post, simply put ‘h2’ as the tag. But if you only want H2’s with the ID of ‘ad-here’ then you’d specify ‘h2#ad-here’ for the tag. Classes are supported to – so you could look for all H2’s with the class of ad-here using ‘h2.ad-here’.
  • tagCounter – this is how many occurrences of the tag must appear in the document before the injection will begin. In the example you can see each h2 specified has a tagCounter that goes up by one each time, so a different adCode is placed before each h2. This is necessary for EZoic, but isn’t for Google AdSense for example.
  • repeatEvery – this is how often the injected code should be added to the output. If you want every second h2 to have an ad for example, the repeatEvery 2. If the ad code should not be repeated, then use 0. Any positive integer is valid.
  • adCode – this is the actual advert code (or any other HTML or script you wanted added) that should be added to display what you want. Due to JSON limitations, unfortunately this must be all on one line in the config file. Yep, it’s a pain. Sorry.
  • position – this can be one of four values, beforebegin, afterbegin, beforeend, afterend – this determines where the code will be placed relative to the HTML element that’s been found.

If you don’t want any ads, simply create this file as an empty JSON array. If you don’t create the file at all it’s likely the package will error out. I guess I could check for that really 🙂

Install the Dependencies

This is easy.

npm i

This’ll take a few minutes depending on the speed of your internet. All dependencies should be downloaded including eleventy itself.

Build the Static Site From WPGraphQL Data

Again, this is pretty easy.

npm run build


npm run server

This latter one will run the built in HTTP server after it’s built the site which will allow you to view the results by visiting – usually – http://localhost:8080 and browse your new static WordPress site generated by Eleventy.

In Case You Missed It

You must set your permalinks in the front matter to match the WordPress permalink structure. Otherwise, any links embedded in posts or pages will be broken. The recent posts page will probably work still though.

There’s no ability for Eleventy to redirect old URLs to new URLs either – you’d have to set that up on your final server using either .htaccess files or nginx config. Unless you use something like Netlify or Github Pages – in which case you’re on your own because I have no idea about them, sorry.

Finally, if you prefer to see me set it up from scratch I’ve made a YouTube video below. It’s about 20 minutes long and goes into a fair bit of depth about it all.

Incidentally, you’ll note that I haven’t yet (at the time of writing) switched Most Useful to static. That’s a time issue – and a lot of my internal links are broken and rely on redirects. I need to fix them first. Once I do though I will be switching Most Useful to static.

If you’d like to see an actual real life site using this package (and the reason why I developed it in the first place) check out https://www.beardeddragonsrock.com which is now all completely static using the 11ty-wordpress-graphql package.

If all of this sounds and looks far too complicated and all you want is fast WordPress web hosting, I highly recommend Rocket.Net Managed WordPress hosting. I have used them myself and they really do work well. Fast and secure. A more in depth look review of Rocket.Net including how to use their service is also available here.

If you’ve found this post useful, or have any questions about the package please leave a comment either on the YouTube video or here.