|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Moved to Eleventy After Ten Years With Jekyll |
| 4 | +description: Things are looking good with Eleventy |
| 5 | +categories: ["Jekyll", "Eleventy", "Coding"] |
| 6 | +--- |
| 7 | + |
| 8 | +Based on the git log, it’s been about six or seven months since I moved this blog over to Eleventy. I did take notes at the time and even started drafting a post about it, but then life happened. Things shifted, priorities changed, and that early draft is probably lost for good now. |
| 9 | + |
| 10 | +So instead, I’m writing this from memory. I’ll try to cover what I did and why, though I can only recall one specific citation. The rest? Let's make some assumptions. 😄 |
| 11 | + |
| 12 | +For years, this blog was powered by Jekyll, using GitHub Pages - all provided by the good people of Github - which meant I could push to the main branch and the whole thing would build and deploy on its own. |
| 13 | + |
| 14 | +Setup details, more or less: |
| 15 | + |
| 16 | +- Jekyll handled Sass preprocessing from some very old CSS files I wrote at the start of this blog. |
| 17 | +- There was also some magic JavaScript bundling, cobbled together from a guide I [created](https://codegazerants.com/2016/01/09/a-jekyll-workflow-with-gulp/) nine years ago and never touched it again. |
| 18 | +- It all just worked, until it didn’t. |
| 19 | + |
| 20 | +## The Reason for Change |
| 21 | + |
| 22 | +Jekyll itself wasn’t the problem. I liked it. Still do. But Ruby on a Mac can be a headache, especially when you don’t live in that ecosystem. |
| 23 | + |
| 24 | +My old Mac? Jekyll ran fine. Why? No idea. Some mix of good luck and forgotten installs. But when I tried to get it running on a new machine, everything broke. I believe the last time I tried, I didn't manage to make it work even after a few hours, and I do like things simple. |
| 25 | + |
| 26 | +I wanted a setup that didn't argue with me. It was time for a change! |
| 27 | + |
| 28 | +## The Plan |
| 29 | + |
| 30 | +I knew I had to solve a few things quickly: |
| 31 | + |
| 32 | +- Find a Jekyll alternative that could preserve my URL structure. |
| 33 | +- Migrate all existing posts and templates. |
| 34 | +- Set up a build pipeline to deploy automatically through GitHub Pages. |
| 35 | +- Do it fast. If it took more than an afternoon or two, I'd probably abandon it and never come back. I had done something similar in the past, but as soon as I managed to make something work I lost my interest. |
| 36 | + |
| 37 | +## The Candidates |
| 38 | + |
| 39 | +I started with Next.js. I'd been messing with it recently, so it felt like a natural first option. I got most of the migration done before realizing it was overkill. Too many moving parts. The URLs didn't work as I wanted. Everything felt heavier than it needed to be, especially for a blog. |
| 40 | + |
| 41 | +So I looked elsewhere. Enter Eleventy. |
| 42 | + |
| 43 | +I’d had my eye on 11ty for a while but never used it seriously. One of the downsides of Eleventy is the documentation. At that time at least, it was more of a reference than documentation, so it was... okay. But there were enough blog posts and migration guides to piece things together and don't get me wrong, the people at 11ty are trying their best. |
| 44 | + |
| 45 | +Now that I'm thinking about it, why wasn't I using ChatGPT during all this? |
| 46 | + |
| 47 | +After a one or two afternoons of reading and tinkering during a weekend, the blog was up and running again at least locally! |
| 48 | + |
| 49 | +## Eleventy Configuration |
| 50 | + |
| 51 | +Most of Eleventy’s logic lives in `eleventy.config.js`. You can break things out more if you want, and structure it as any JS library, but this setup was enough for me. I also added two config files in, `_posts` and `_data`. |
| 52 | + |
| 53 | +Here’s where I defined the preprocessing behavior, added collections, and plugged in a few filters. For CSS, I went with PostCSS and some basic plugins: |
| 54 | + |
| 55 | +```js |
| 56 | +eleventyConfig.on("eleventy.before", async () => { |
| 57 | + const cssSourceFile = "./assets/css/index.css"; |
| 58 | + const cssDestinationFile = "./_site/index.css"; |
| 59 | + |
| 60 | + fs.readFile(cssSourceFile, (err, css) => { |
| 61 | + postcss([postcssImport, postNested, autoprefixer, cssnano]) |
| 62 | + .process(css, { from: cssSourceFile, to: cssDestinationFile }) |
| 63 | + .then((result) => { |
| 64 | + console.log("Writing CSS to _site"); |
| 65 | + fs.writeFile(cssDestinationFile, result.css, () => true); |
| 66 | + }); |
| 67 | + }); |
| 68 | + |
| 69 | + eleventyConfig.addWatchTarget("./assets/css/"); |
| 70 | +}); |
| 71 | +``` |
| 72 | + |
| 73 | +For collections, I added one for posts and another for categories: |
| 74 | + |
| 75 | +```js |
| 76 | +eleventyConfig.addCollection("posts", (collectionApi) => { |
| 77 | + return collectionApi.getFilteredByGlob(["_posts/*"]).reverse(); |
| 78 | +}); |
| 79 | + |
| 80 | +eleventyConfig.addCollection("postsByCategory", (collectionApi) => { |
| 81 | + const posts = collectionApi.getFilteredByGlob(["_posts/*"]).reverse(); |
| 82 | + const categoriesMap = {}; |
| 83 | + |
| 84 | + posts.forEach((post) => { |
| 85 | + const categories = post.data.categories || []; |
| 86 | + categories.forEach((category) => { |
| 87 | + if (!categoriesMap[category]) { |
| 88 | + categoriesMap[category] = []; |
| 89 | + } |
| 90 | + categoriesMap[category].push(post); |
| 91 | + }); |
| 92 | + }); |
| 93 | + |
| 94 | + return Object.entries(categoriesMap).map(([category, posts]) => ({ |
| 95 | + category, |
| 96 | + posts, |
| 97 | + })); |
| 98 | +}); |
| 99 | +``` |
| 100 | + |
| 101 | +To replicate Jekyll’s `excerpt` filter, I added this: |
| 102 | + |
| 103 | +```js |
| 104 | +eleventyConfig.addLiquidFilter("excerpt", function (input) { |
| 105 | + if (!input) return ""; |
| 106 | + const separator = "</p>"; |
| 107 | + return input |
| 108 | + .split(separator)[0] |
| 109 | + .replace(/<script.*?<\/script>/gs, "") |
| 110 | + .replace(/<!--.*?-->/gs, "") |
| 111 | + .replace(/<style.*?<\/style>/gs, "") |
| 112 | + .replace(/<.*?>/gs, ""); |
| 113 | +}); |
| 114 | +``` |
| 115 | + |
| 116 | +You can check this file on [Github](https://github.com/codegaze/codegaze.github.io/blob/master/eleventy.config.cjs) of course for all the contents! |
| 117 | + |
| 118 | +As mentioned, I also added: |
| 119 | + |
| 120 | +- [`site.js`](https://github.com/codegaze/codegaze.github.io/blob/master/_data/site.js) for shared variables. |
| 121 | +- [`_posts.json`](https://github.com/codegaze/codegaze.github.io/blob/master/_posts/_posts.json) to keep paths consistent with Jekyll. |
| 122 | + |
| 123 | +## Non-Mandatory Updates |
| 124 | + |
| 125 | +During the migration process I made some other updates that really simplified things: |
| 126 | + |
| 127 | +- Removed all old JS build steps and ended up with just seven dependencies. Five are for CSS. Two are Eleventy itself. |
| 128 | +- Simplified the CSS setup. Sass was overkill. I switched to native CSS variables, kept nesting via PostCSS, and stuck with BEM. Everything stayed in separate files, which keeps me happy. |
| 129 | + |
| 130 | +No big flashy features here, but it felt good to clean house. Small dopamine dose! |
| 131 | + |
| 132 | +## The Build Pipeline |
| 133 | + |
| 134 | +Once the blog was working locally, I needed a way to deploy it. |
| 135 | + |
| 136 | +Of course I looked for something that Github Actions would help. There were a bunch of solutions that used a secret or something like that which I tried to avoid. |
| 137 | + |
| 138 | +Somewhere along the way, I found [`actions/upload-pages-artifact`](https://github.com/actions/upload-pages-artifact). I can’t remember where, maybe GitHub Docs, maybe a blog post. Either way, it did the trick. |
| 139 | + |
| 140 | +One more thing, because the repo is used for Github Pages and we are creating our own build pipeline, we need to inform Github about this. I added an empty `.nojekyll` file to skip their automation and let my build handle everything. |
| 141 | + |
| 142 | +## Final Thoughts |
| 143 | + |
| 144 | +It’s been months since I finished this migration the beggining of this year. I’ve barely touched the setup since and things seems to be working even in a machine that I just installed it. That’s a good thing. No... That's a very good thing. Initial goal is done! |
| 145 | + |
| 146 | +It runs. It builds. It deploys. |
| 147 | + |
| 148 | +If it holds together for another ten years like Jekyll did, I’ll call that a success. |
| 149 | + |
| 150 | +And one last thing: I still think Jekyll is great. It served me well for a long time. My move away from it was more about my limited Ruby skills and a desire for a simpler experience than any fault in the tool itself. |
| 151 | + |
| 152 | +My suggestion would be to give it a try and see if it works for you. The team has done some amazing work. All the contributors, they’ve built something solid and lasting. |
| 153 | + |
| 154 | +## Assumed Citations |
| 155 | + |
| 156 | +- [https://kittygiraudel.com/2020/11/30/from-jekyll-to-11ty/](https://kittygiraudel.com/2020/11/30/from-jekyll-to-11ty/) |
| 157 | +- [https://24ways.org/2018/turn-jekyll-up-to-eleventy/](https://24ways.org/2018/turn-jekyll-up-to-eleventy/) |
| 158 | +- [https://alex.pearwin.com/2020/06/jekyll-to-eleventy/](https://alex.pearwin.com/2020/06/jekyll-to-eleventy/) |
| 159 | +- [https://github.com/11ty/eleventy/discussions/1455](https://github.com/11ty/eleventy/discussions/1455) |
| 160 | +- Dozens more, probably. It was a very productive weekend. |
0 commit comments