Iāve spent the last few weeks distracting myself from things by dabbling with Eleventy (11ty) ā āa simpler static site generatorā. Iād been meaning to take a look at it for a while, having decided that it was time to break away from WordPress (for this site at least), and I was sure that static was the way to go. Iāve used Hugo and Gatsby before, but all the cool kids are talking about 11ty, so I thought Iād make the most of the lockdown and give it a go whenever I had an hour or so free.
What youāre looking at now are the fruits of that labour. If you were familiar with the old site, you probably wont notice much different; itās the same basic design and structure, with only a few visual tweaks. Behind the scenes though, big tings.
All things considered, the whole process was pretty smooth, and I could definitely have been done much sooner if Iād given it more than my casual attention. Iāve enjoyed the excuse to learn something new and Iāve appreciated the comprehensive documentation which has helped me make sense of things. Iām also indebted to the people whoāve made their own 11ty work public on GitHub. I didnāt use any of the base builds that are floating around, but I did pick up all sorts of bits from all over the place (particularly Kristoff Michiels, Sarah Fossheim, Tatiana Mac, and James Doc). My own contribution is here: https://github.com/mattnortham/ma11northam though Iām certainly not presenting it as any sort of standard.
Likewise, here are a few notes on the process that are by no means a āguideā, but might help you if youāre getting to grips with 11ty (and will serve as a reminder to me when I next come to do this). Theyāre conveniently split into 11 points which I PROMISE was not intentional, but Iāll happily accept.
- Getting content out of WordPress
- Handling images
- Markdown It
- Dates
- Console.logging
- Building collections
- Content management
- Deploying to your own hosting
- Performance
- Liquid
- Some other little things
Getting content out of WordPress š
I used WP Gatsby Markdown Exporter to grab my existing content. It does a great job at converting posts into the correct format and packaging it up in manageable directories (as well as a copy of all uploaded media). That bit was quick. What took much longer though, was the tidying up. I had a lot of front matter that I didnāt want any more, and some of the content itself needed amending (image markup & media embeds were the main culprits). I still havenāt finished going through all those old posts yet (Iām back to 2018 so far) but though itās tedious, itās actually pretty useful in terms of prompting me to review and audit it all. Iāve sanitised tags, fixed broken links, and formatted posts with a bit more consistency. Well worth it.
Handling images š¼
It took me a while to get images behaving in a satsifactory way and I still havenāt really got it sorted. My main problem was in serving them up from the markdown files, and though itās not entirely resolved (adding a class, anyone? <figure>
?), I do at least have them lazyloading (with a <noscript>
fallback) after rolling my own Markdown It plugin (more on that later).
Iāve also made use of a couple of shortcodes to render appropriately sized images in my liquid templates, which was uber important due to the number of images Iāve got in the photography section. It doesnāt go as far as responsive images yet, but does at least show small images where I want small images, and big ones where I want big ones. A little bit like this:
// Usage: {% smallImg "PATH-TO-IMAGE", "The alt", "align-left" %}
smallImg: (img, alt, className) => {
let i = img.lastIndexOf('.');
let imgPath = img.substring(0, i);
let ext = img.substring(i + 1);
let size = '-sm';
let theImage = `${imgPath}${size}.${ext}`;
if (className == "lazy-img")
return `<img data-src="${theImage}" alt="${alt}" class="lazy-img img-small ${className}">
<noscript><img src="${theImage}" alt="${alt}" class="img-small"></noscript>`
else
return `<img src="${theImage}" alt="${alt}" class="img-small ${className}">`
}
Markdown It š
Speaking of Markdown It, setting the typographer
option is a must " " š.
const mdOptions = {
html: true,
breaks: true,
linkify: true,
typographer: true
};
The plugin I bodged together to wrap images (which you can see here) was inspired by markdown-it-plugin-data-src.
const imgDataSrc = require("./src/_11ty/[imgDataSrc.js");
...
eleventyConfig.setLibrary("md", markdownIt(mdOptions).use(imgDataSrc));
The reason I made my own was because I wanted to use a different lazyloading method, as well as the <noscript>
too. For the JS, Iām making use of vanilla-lazyload, as thatās what I had before and Iāve not got any reason to stop using it. (Itās now the only bit of JS that gets applied sitewide).
Dates š
I made use of luxon to create a couple of date filters, for blog posts and the RSS feed.
readableDate: (dateObj) => {
return DateTime.fromJSDate(dateObj, {zone: 'gmt'}).toLocaleString(DateTime.DATE_FULL);
},
timeStamp: (dateObj) => {
return DateTime.fromJSDate(dateObj, {zone: 'gmt'}).toFormat('yyyy-LL-dd HH:mm:ss');
}
But the built in date filters are also pretty good, using the syntax from strftime like {{ post.date | date: "%B %Y" }}
(which outputs April 2020
). In fact, I canāt 100% remember why I created those filters when I could possibly have used those š¤.
Still not found a simple way of adding the day suffix (st/nd/rd/th) for the readable date though.
Console.logging š“
Console log is a pretty recent addition. As a unashamed fan of debugging in this way, I appreciated that this is now built in. You can use it for any bit of data. I mostly found it useful to check what was making it into collections, but tbh itās a bit of a messy way to work, as the log gets output alongside all the build notifications when running --serve
in the terminal.
{{ featuredImage | log }}
Building collections š¦
Thereās a lot written about creating collections, and handling blog posts was pretty straightforward. I liked the approach I found in Kristoffās code of having the main post collection, and then other collections where all posts are grouped by tag and/or category. Itās a little more legwork, but made more sense to me when it came to rendering archive pages.
Beyond blog posts, I did find it a little tricky to come up with a way of managing my image galleries. I wanted to have a collection of all my images that I could loop through by tag, without creating pages for them all (because I had hundreds and it was taking a while to build, not to mention I didnāt ever link to them) ā thatās where permalink: false
in the frontmatter came in.
But then I wanted to have pages created only for photos with a particular tag (āprintā, indicating you can buy a copy of it). To do that, I needed to create pages from a subset of the main collection, by using ---js
instead of vanilla frontmatter, which allows me to apply a before callback. You can see it on my print.liquid file.
...
pagination: {
data: "collections.allPhotos",
size: 1,
alias: "photo",
before: function(data) {
return data.filter(function(item){
return item.tags.includes("print");
})
}
}
What Iāve ended up with does feel a little convoluted, with 5 collections on the go for my photography (as well as all the blog collections). But it works, and itās quick to build, so thatāll do for now.
Content management š
Iām not really using a CMS at the moment. Plenty of talk out there about using Netlify CMS but I havenāt made any move in that direction yet. What I am using is stackedit to assist with my markdown where needed (Iāve never relly gelled with it, though itās growing on me), and handcoded blocks for my liquid pages such as about me.
Iāve also retained a fragment of my WordPress set up to manage my photos. All the details for them are curated in WP then made available as a json file which I manually copy across to the 11ty _data
directory as photos.json. That then gets picked up by front matter pagination to create the collections I mentioned before.
Itās fine. I donāt intend to change content much, but if it becomes unmanageable, Iāll look into a different approach.
Deploying to your own hosting š
Contrary to general concensus, Iām not using Netlify to host my site. I already have my hosting and domain and SSL configured and paid for, so I wanted to stick with it. Frustratingly, I couldnāt find much in the way of documentation to go along with how to deploy to anywhere other than Netlify (or GitHub Pages), but I got there in the end.
Iām making use of GitHub Actions, having created a workflow file to watch for any commits to the main
branch. It runs the 11ty build command then pushes it to a built
branch thanks to an action intended for use with GitHub pages, and thatās where I was stuck for a while. Iāve used a GitHub workflow making use of SFTP before, but couldnāt get it to work in this particular set up.
Eventually, I opted for a middleman (š Buddy) which fills the CI gap with a pipeline that watches my built
branch and then finally deploys via SFTP. It sounds more complicated than it is, and yes ā itās FTP š“š», but Iām really pleased with how quick and seamless it actually is.
Performance š
Everyone raves about the performance gains that can come from using a static site generator like 11ty, and rightly so. The improvements can be dramatic and theyāre of course very welcome. #perfmatters.
Butā¦ Iād actually worked really hard to get my old site performing well. Yeah it was WordPress but that doesnāt automatically mean āslowā. So when it came to testing this new site, the improvements were so minimal ā and the issues that existed were of course the same. I would hope that it goes without saying but ājust usingā 11ty isnāt going to immediately grant your Lighthouse wishes.
There are other benefits away from the digits at the top, but itās those numbers that get you on the 11ty Leaderboards [I still donāt know how? I want to be on there!], and purely on those numbers, my WP site more than held its own.
Sidenote: on my old WP site, I made use of some randomly generated SVG wave transitions to slightly mask the minimal loading times between pages, and while I still love the effect, I thought it probably unnecessary with this new site so theyāre gone (I may still bring them back š they were pretty).
Liquid š¦
I used Liquid for my template files (primarily out of respect to Liquid Swords ā word to GZA ā and Iām loving how easy it is to use. But most people seem to use Nunjucks, so some of the syntax differences caught me out, such asā¦
š¤ set
in Nunjucks == capture
in Liquid (src).
š¤ In Liquid, elseif
is actually written elsif
because of course, why would it need that second āeā(?) š (src).
š¤ Within a forloop, to use a counter, I tried {{ assign i++ }}
but it didnāt do anything. The docs recommend using increment: {{ increment myVar }}
but spits it out on the page. So I ended up finding forloop.index and using {% assign num = forloop.index %}
in order to track the iteration.
š¤ or
doesnāt seem to work in liquid templates, despite it being referenced widely. Plenty of examples of 11ty code show things like: <title>{{title or metadata.title }}</title>
but I had to change it to messier looking if
statements to get it to work:
<title>{% if title %}{{title}}{% else %}{{metadata.title }}{%endif%}</title>
ā¦ and finally š
A few little things that made me pull my hair out before realising they were simple fixes.
š When using a 11ty.js data file (like I am to generate different image sizes), you need to add them to the templateFormats in the eleventy config or they donāt get picked up. This took me a LONG time to realise: templateFormats: ["md","html","liquid","11ty.js"]
š If youāve got tags being set in Frontmatter and a directory data file, and want to merge them, use deep merge: eleventyConfig.setDataDeepMerge(true)
And thatās it.
If Iām honest, I didnāt really have anything against the old WordPress site other than the ongoing fear of losing everything whenever there was an update š¬. I managed to do pretty much anything I needed to do, and I was comfortable developing with it. But, Iād had that site for 14 years and when you add on and add on to something for that longā¦ It felt right to change it up and start from fresh (albeit, with the same design and some of the same CSS). Itās good to get out of your comfort zone. 11ty ticks a lot of front-end developer boxes for me, and Iām looking forward to working with it some more š.
Some things left to do / look at
- Related posts
- Blog search
- Service workers
- Fonts that arenāt on Google
- CMS
- Colour theme switcher
- Responsive imagesā¦ images with captions
- Actual pagination on the archive pages
- Various bits of content to migrate / create
- Blog posts back to 2008
- A lot more photo collections
- TIL
- Work portfolio
Pop back soon to see the progress š