I announced it on twitter last week and here you go with my new blog post about the migration from GatsbyJs to 11ty. In this post, I explain why I migrated to Eleventy, my challenges, and how you can avoid them.

I read much about Eleventy the last month and its creator Zach Leatherman. I got curious as I saw that it needs zero client-side JavaScript.

Eleventy is a simpler static site generator.

I try to have about 2 hours to one day a week to try something new for education purposes. So I decided to try out Eleventy. I could use it for my clients who only need a static landing page. I ended up migrating my whole website from GatsbyJs to 11ty.


In this post, I show you why I migrated my website from GatsbyJs to Eleventy, my challenges, and how you can avoid them. This post tries to outline the main advantages and disadvantages of Eleventy compared to GatsbyJs.

Table of Contents

  1. What is Eleventy, and how does it work?
  2. What is GatsbyJs, and how does it work?
  3. Why I struggled with GatsbyJs?
  4. My migration from GatsbyJs to Eleventy
  5. Is GatsbyJs a wrong choice?
  6. Next steps
  7. Conclusion

What is Eleventy, and how does it work?

Eleventy is a simple static site generator. That’s it. It uses data and templates to generate HTML files you can upload to your hoster and serve them statically.

That is almost all you need to say about Eleventy. It is fascinatingly simple. Of course, we will dive more in-depth, and there is a lot more to mention, but the paragraph above describes 11ty in its core concept.

You start with Eleventy by choosing your preferred template engine. Probably the easiest is markdown. The following file shows a simple markdown example for eleventy. Eleventy uses your file structure to generate HTML files.


# My custom headline

Now let’s run this simple example with: npx @11ty/eleventy. This command will generate a _site directory with an index.html containing the following markup.


<h1>My custom headline</h1>

What if you have more complex content that you can not display with markdown? Eleventy supports multiple template engines you can use.

Template engines

  • HTML *.html
  • Markdown *.md
  • JavaScript *.11ty.js
  • Liquid *.liquid
  • Nunjucks *.njk
  • Handlebars *.hbs
  • Mustache *.mustache
  • EJS *.ejs
  • Haml *.haml
  • Pug *.pug
  • JavaScript Template Literals *.jstl


While I tried out some of the templates, I recognized how fast I could create pages. I went with Nunjucks as it is very flexible. In no time, I created pages and wrapped them with layouts. Layouts are some special templates in Eleventy you can refer to from your pages. A layout for our example above could look like this:


layout: main.njk

# My custom headline


title: My tutorial

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Why I migrated my website from GatsbyJs to Eleventy</title>
    ... contents

The layout in the _includes folder wraps the index.md page and outputs all to the _sites folder.

Data Cascade

Working with data in eleventy is very simple. The data is merged from different sources before the engine renders the template. The data-merging is called Data Cascade, and it contains the following parts.

  1. Computed Data
  2. Front Matter Data in a Template
  3. Front Matter Data in Layouts
  4. Template Data Files
  5. Directory Data Files (and ascending Parent Directories)
  6. Global Data Files
  7. Custom Global Data


You can use Eleventy without any configuration, but if you want to add some additional features or use a plugin, you can add it to your .eleventy.js file and expand the functionality.

Filters and Shortcodes

With filters and shortcodes you can expand the template functionality. For example, you could define a shortcode that renders a button or a filter that formats a date.

What is GatsbyJs, and how does it work?

Gatsby is a static site generator as well. It is React-based and uses GraphQL. It is preconfigured and has used many tools you need to implement, usually by yourself, like webpack or a service worker. Gatsby uses the pages directory to create each page for your site. It has a huge community and a wide range of plugins with whom you can expand your website’s functionality.

It builds its data-layer with GraphQL and transforms your JSON, markdown files, or external API data to nodes you can use and query in your templates. You can start very fast with your first GatsbyJs site with the Quick Start on the GatsbyJs documentation site. Last year I did a web performance experiment and chose GatsbyJs because they promise a blazing fast site.

Why I struggled with GatsbyJs?

GatsbyJs is an excellent framework, and while many developers do not like ReactJs because of its performance bottlenecks, I found myself happy with the developing experience. If you didn’t read through my web performance experiment, I had some trouble after I launched my site. I knew I would have some performance issues to face, but I wasn’t expecting such big ones.

My site was slow even while I used “blazing-fast” GatsbyJs. Of course, some issues weren’t related to Gatsby, but Gatsby was part of the problem. I spend hours over hours optimizing my site. Even though I know what I am doing, it was pretty challenging and took much longer than developing my website from scratch.

Gatsby needs much client-side JavaScript to work. If you work on web performance, you know it’s good to reduce client-side JavaScript to a minimum. Especially if you don’t need JavaScript. If you are not into that topic, check out how the browser parses JavaScript in my blog post about JavaScript high performance and especially my series about the Business Value of Speed where I go through the sequence of steps the browser needs to process before it can paint a pixel.

I wanted to reduce the amount of JavaScript and was quite successful with a plugin called gatsby-plugin-preact. It replaces React with Preact and cut the bundle files size of my framework-[hash].js from ~40kB to 8.6kB. That was great, but at the same time, it was a bit strange to erase the developing framework React at build time.

Nevertheless, I still struggled with all of my components. I did some research and found the plugin gatsby-plugin-no-javascript. It removes JavaScrpt at build time. I looked at the file size and was happy for a moment. Just for a moment because I knew it breaks my website. I’ll tell you the truth. I wasn’t able to reduce the amount of JS to the proper file size. While I write this post, I still have 81.8kB of JavaScript for the main app rendering my primarily “static site”.

Not to mention that I use lazy loading like a freak, so additionally, I have 20 requests to JS files that are loaded later between 2kB and 25kB. You could say let’s reduce the JavaScript of our components. I did this for hours. I deleted code, I changed libraries, and I removed functionality.

My migration from GatsbyJs to Eleventy

Here comes Eleventy. I now migrated all my content to 11ty and implemented all interactions with JavaScript that I need. I now have one main.js of 2.2kB and two bundles that are lazy-loaded with webpack on the pages that need them. One with 941 B and one with 678 B. The significant point is that I didn’t remove any functionality.

The following table shows you the size of all MIME Types before and after the migration.


MIME TypeBytesUncompressed


MIME TypeBytesUncompressed

So, where did I started? index.js. Nope. As my home page is an overview page, I started with my last blog post. I write my blog posts in markdown and use frontmatter in the file’s head for additional information. This blog post you currently reading looks like this:

  - 'javascript'
  - 'webperformance'
layout: layouts/post.njk
article: true
title: 'Why I migrated my website from GatsbyJs to Eleventy'
date: '2020-08-05'
author: Marc Radziwill
    follow: 'index,follow',
      'blog: Why I migrated my website from GatsbyJs to Eleventy - Marc
      'Eleventy is the new runner up in the JAMstack community. Read why I
      struggled with GatsbyJs and why I choose Eleventy for my website >>',
categories: ['javascript', 'webperformance', 'business']
  - webperformance
  - frameworks
    src: ./src/blog/business-value-of-speed-part-two-metrics-and-mapping-of-business-values/images/business-value-of-speed-part-two-metrics.jpg,
    alt: 'alt text',
    title: 'image title',
readingDependencies: You must be at least a level beginner to make this happen
readerLevel: beginner
published: true
isTechArticle: true

These files have quite some information in them. In Gatsby, I needed to create NodeFields to query them. So for every entry, I did:

  name: 'title',
  value: node.frontmatter.title,

In Eleventy and due to their data cascade these values are already accessible in template file for example if you loop through a collection of pages with in the data Object like this:

{%- for page in collections.all -%}
  <h2>{{ page.data.title }}</h2>
{%- endfor -%}

After one hour, I migrated all my posts content without the images. I was convinced and decided to migrate my entire content. That was what I was looking for.

I continued by defining a layout for my base pages and my blog pages to serve different CSS and JS files. I built the main components and Nunjunk partials like the header and the footer, and I created some shortcode components like a button.

One week later, I am ready for my first test with my site running completely on Eleventy. I was fast. Faster than I ever thought, I could be re-writing my whole website. But I also was struggling with some parts.

Words about images

Images were my biggest problem. My site contains many header images that I want to render in a picture-tag with correct sizes and formats that the browser can decide which image it should download. Gatsby has a smooth plugin that handles images, and for Eleventy, I chose the plugin eleventy-img and wrote a Nunjunk async shortcode to render the images before the blog content starts.

Async image shortcode

{% resImage theme.logo.src, "alt text", theme.logo.options, "title text" %}

That worked quite well for all Nunjunk templates, but I could not use them in my 11ty blog posts as they are based on markdown. For all markdown images below the fold, I implemented a different approach.

First I encounter all img tags with an eleventy transformer for all html files that are in my _site folder. I us the npm package jsdom to make the content of each page selectable and query all images with:

document.querySelectorAll('.post-content :not(picture) img[src]:not([srcset]):not([src$=".svg"])'

I loop through them and create a picture-tag with my resImage async shortcode. The idea for this and some part of the code is from Nicolas Hoizey - Eleventy Image Responsiver. After all, images are converted to a picture-tag with the correct source path, I write them back to the page’s content.

Additionally, I wanted to have my image files located where the blog post file is. This structure makes it easier for me to maintain them and cross-post them to dev.to.

So my file structure looks like this:

│ └───images
│          image-1.png
│          image-2.png
│  index.md

To make this file structure work, I had to change the path of the images depending on their original location. For blog posts, I adjust the output path differently for images located in <root>/assets/images/**. The transformer I wrote resolves the output path depending on the input path.

Is Gatsby a wrong choice?

In a previous version of this article, I wrote this paragraph:

No, not at all. Gatsby was a wrong choice for me, having my requirements and wanting to have a site without much JavaScript, but Gatsby provides some great features. If you are struggling with JavaScript, you should consider migrating to Eleventy. Eleventy is fast and flexible not only while you are developing but also during runtime.

As of today, I changed my opinion. Is GatsbyJs the wrong choice for me and similar websites? Yes, it is the wrong choice. Static sites don’t need GatsbyJs or similar site generators that rely on JavaScript in the frontend. Even if you have some interactive components on your website, you don’t need GatsbyJs. You may ask me where do I need GatsbyJs? I use it for my workshop platform. Also they have a use cases site, but I doubt that you really need JavaScript to render a Technical Documentation, a Company Blog or a Custom Landing Page.

Next steps

I migrated my website in one week from Gatsby to Eleventy. So for the moment, I am delighted and satisfied. For sure, there are still some open tasks that I will work on in the next weeks. If you are thinking about migration, I recommend you try out Eleventy. It is fun, and you will love it! ♥️


In this post, I tried to show you why I migrated my website from GatsbyJs to Eleventy and why I think this is important for a fast site.

Cheers Marc


22.04.2021: Updated the “Is Gatsby a wrong choice” section, added Custom Global Data