Why I migrated this site from Jekyll to Astro

3 August 2023

·

10 min read

A banner image showing a distracted boyfriend walking with his girlfriend (overlayed with the Jekyll logo) and looking amazed at another seductive girl (overlayed with the Astro logo).

I’m primarily a mobile developer, but I like to dabble in web development for my own websites. However, building a website these days is extremely complicated. So much so that it is burning out junior developers before they have even started. I don’t need React and hydration and server side rendering and SPAs and PWAs and tree shaking and what-have-you for a blog. Complexity is the apex predator of the grug brained dev. I just want a nice developer experience writing HTML. I soon figured out that meant I want a template language in combination with HTML. That is exactly what Jekyll does, with Liquid. I’ve been fairly happy with Jekyll as it seems to be well-suited for a blog(-like) website. However, when I needed to pick a static site generator for my new project, feedo.so, I did not automatically pick Jekyll. I first wanted to see what else is out there. So, what made me look elsewhere?

Doubts about Jekyll

A few things, actually. Let’s go over them one by one.

Liquid

Liquid is a templating language originally built by Shopify in 2006 to create themes for e-commerce storefronts. Jekyll adopted it to allow users to write templated HTML for their websites. It looks something like this:

<ul class="post-list">
  {%- for post in posts -%}
  <li>
    <h3>
      <a class="post-link" href="{{ post.url | relative_url }}">
        {{ post.title | escape }}
      </a>
    </h3>
  </li>
  {%- endfor -%}
</ul>

Notice the curly braces? That’s Liquid. It works well enough, but there are a few downsides to this approach. First, it’s a language with limited real world applications. There are quite a number of projects using Liquid, of which Shopify and Jekyll are the main ones, but that’s pale in comparison to the applications written in, say, JavaScript. That means that there is far less information out there, except for the official documentation and open source projects. To illustrate, Liquid has roughly 2500 answered StackOverflow questions at the time of writing. JavaScript has 1.8 million. If you’re dealing with a problem in your JavaScript project, someone has probably solved it already. If you’re using Liquid, you can’t be so sure. (And yes, in this day and age that also means that the ChatGPTs of the world will have had substantially more JavaScript than Liquid in their training sets.)

Second, it’s also limited in its language features. Sure, there’s ifs and fors and the other basics, but there are no functions or classes. There’s no null safety. The standard library is limited to a handful of functions, but there are no third party libraries to make your life easier. This unfortunately means that expressing the logic you want to express is more verbose and and less elegant than it needs to be.

Lastly, since it’s such a limited-use language, I would only write in it if I want to make functional changes to my website. This doesn’t happen daily. This means I constantly forget how things are done. Do I need {{ }} or {% %}? How do I assign a variable? What does that pipe | mean again? I need a refresher every time I come back to Liquid, and that means I’m never going to write it fluently. Of course, if you’re a full-time Shopify theme or Jekyll site developer, I can imagine you would reach fluency. But that’s not me.

Where’s my code?

Jekyll works on the basis of themes, minima being the default one. These themes have layouts, like page.html for pages, and snippets, like google-analytics.html. The problem arises when you want to customize these theme files. You’ll need to create a file with the same name in your project folder, which will cause the theme file to be overridden. Usually you don’t want to override, though. Usually you just want to make some adjustments. To do that, you need to copy the original theme file into your project folder, after which you can make your adjustments. You figure out the original theme file’s location by running bundle show minima, which will most probably return a path not in your project folder, like /home/jay/gems/gems/minima-x.y.z.

Let’s say you overrode page.html but not home.html. If you want to see what home.html is actually doing you have to run bundle show minima again to figure out its location to go look at it. You can’t just navigate to it in your IDE or editor, because it’s not part of your open project folder. This results in a feeling of things being “all over the place”, and means the workflow is different depending on whether you changed this file before or not.

Plugins

If you want to add more advanced build-time logic to your site, you’ll have to resort to writing your own build plugin. This is fine in itself. However, while templates are written in Liquid, build plugins are written in Ruby. At the very least, this results in context (or ‘mode’) switching when working on your site, depending on which part you’re working on. There’s an additional downside for me, which is that I’m not writing Ruby for anything else other than Jekyll sites. That means the downside of limited fluency mentioned for Liquid applies here as well.

Also, there’s this sentence from the plugins documentation:

If your [plugin] is split across multiple files, it should be packaged as a Rubygem to be published at https://rubygems.org/.

This requirement means that all your hacky, one-off plugins need to be published. They’re not part of your site’s source code, so making changes to them is even more convoluted. (Make a change → Publish new version → Download new version in your project → Use.) It would improve the developer experience significantly if this requirement could be solved, and it would be possible to have build plugins as part of your project, no matter the number of files they consist of.

Looking for alternatives

My main gripe with Jekyll is that I got the feeling the developer experience could be better. So when I went looking for an alternative, I wanted something which does templating in a more conventional language, makes all layout (theme) files available in the project directory and makes it easier to add build-time logic, should that need arise.

Moreover, my existing requirements, which Jekyll already satisfied, still stand. This mostly boils down to sending as little JavaScript to the client as possible, and no hard requirement on server side rendering. The former keeps the site light on bandwidth and great on performance, and the latter keeps the site maximally flexible in terms of hosting.

I was (and still am) always intrigued by Next.js, but this would lock me in to writing React, and I wasn’t sure if I was ready to make that jump. I’m a big fan of Kotlin, so I briefly looked for ways to utilize this language for my web development needs, but most solutions at the time didn’t seem mature enough. And then I stumbled upon Astro…

Upsides of Astro

Astro’s landing page already boasts about a lot of features that speak to me. It lists zero client-side JavaScript by default, freedom to pick and choose UI frameworks (’none’ is okay too) and flexibility in hosting options. I don’t want to parrot the landing page of course, so let’s go over some of the main points that sold Astro over Jekyll for me.

Everything is TypeScript

Rather than Liquid, templating in Astro is done in TypeScript (JavaScript). This is a far more conventional language, meaning it is far easier to find information online. It is also way more likely that any given developer is fluent in TypeScript than in Liquid.

Not only templating, but any build-time plugins (called “integrations”) are also written in TypeScript. This keeps context switching to a minimum and allows for maximum flow when working on your site.

It’s all in the DX

The developer experience with Astro is great. Some of my personal highlights:

Maximum flexibility

This one is huge actually. Complexity is a choice with Astro. If you just want to write templated HTML (which I do, at the moment), you can do that. If you want to use React or Svelte or Vue or other UI frameworks, you can do that too, but you don’t have to. You’re not locked in to any framework, and that’s great. Deferring hard-to-reverse choices in programming is generally a good thing. This puts Astro at an advantage over both Jekyll and Next.js, where you’re locked in to either no UI frameworks or React, respectively.

But it doesn’t stop at UI frameworks. Want to use Tailwind for CSS? You can. Want to connect a CMS, like Ghost? Go ahead. Want to add a Backend as a Service, such as Firebase or Supabase? No problem. This flexibility means that even if you’re creating a simple blog today, it has the freedom to grow into something bigger tomorrow, without requiring an expensive migration to get there.

Astro feels like a big buffet. You can just pick and choose the tools you want to use to build your plate, err…, website.

The great migration

These reasons were compelling enough for me to start my new project, feedo.so, using Astro. I had such a good experience, that I wanted to use it for the site you’re currently reading, shortway.io, too. Now, I’m quite weary of making changes to software just for the sake of making changes, but I figured if I want to make this change I should do it now. It is going to be far more costly to migrate when I have hundreds (okay, tens) of blog posts up already, than it is now, with just two.

So last week I got to work. It took me a few days of basically rebuilding Jekyll’s minima theme in Astro + Tailwind. (I did not want to spend time thinking about looks at this stage.) I encountered virtually no issues, and the result is what you’re looking at now. I’m pretty happy with the result, and now it’s time to start filling this site with some more content.

If only Compose for Web gets stable soon enough, I might have another migration to write about. :) Just kidding! (I think…)

Are you also using Astro? Or Jekyll? Do you agree or disagree with my reasoning? I’m curious to hear from you! Feel free to leave a comment on Twitter (I mean ‘X’), Mastodon, Bluesky or Threads. Thanks for reading!

One more thing…

Do you love newsletters? But hate a cluttered inbox? Then you might like Feedo, which I built to solve this! Feedo takes your newsletters out of your inbox, and presents them in a beautiful feed.

More reasons to love Feedo: Download Feedo now on Google Play! Google Play Store