Mastering Eleventy (11ty): The Ultimate Guide to Fast, Flexible Static Sites

Introduction: The Quest for the Perfect Web Performance

In the modern era of web development, we have often found ourselves trapped in a “JavaScript-first” cycle. We use massive frameworks like React or Angular to build simple marketing sites or blogs, only to realize that the end product is bloated, slow to load on mobile devices, and a nightmare for SEO. This is often referred to as “JavaScript fatigue.”

The problem is clear: Why ship megabytes of JavaScript to a user just to display a few paragraphs of text and an image? This is where Static Site Generators (SSGs) come to the rescue, and one tool has risen above the rest for its simplicity and power: Eleventy (11ty).

Eleventy is a simpler static site generator that was created to be a JavaScript alternative to Jekyll. It is written in Node.js, but unlike Next.js or Gatsby, it does not force you to send any client-side JavaScript to your users. It transforms your raw content—Markdown, JSON, or various template formats—into pure HTML. The result? A website that is incredibly fast, highly secure, and easy to maintain.

In this comprehensive guide, we will walk through everything you need to know to become an Eleventy expert. Whether you are a beginner looking to build your first portfolio or an expert seeking a more decoupled architecture, this guide provides the roadmap to success.

Why Choose Eleventy Over Other SSGs?

Before we dive into the code, it is important to understand the philosophy behind Eleventy. In a market crowded with tools like Hugo, Jekyll, Gatsby, and Astro, why should you choose 11ty?

  • Zero-Config by Default: You can start with a single Markdown file, and Eleventy will build it without you needing to create a complex configuration file.
  • Decoupled from Frameworks: You are not tied to React, Vue, or Svelte. You can use whatever you want, or better yet, nothing at all.
  • Multiple Template Languages: Eleventy supports Markdown, Liquid, Nunjucks, Handlebars, Mustache, EJS, Haml, Pug, and even JavaScript Template Literals. You can even mix and match them within the same project.
  • Speed: Because it outputs plain HTML, your site achieves perfect 100/100 Lighthouse scores with minimal effort.
  • Incremental Adoption: You can move an existing site to Eleventy piece by piece.

Phase 1: Setting Up Your Development Environment

To follow this tutorial, you will need a basic understanding of the terminal and have Node.js installed on your machine. Eleventy requires Node.js 14 or higher, though I recommend using the latest LTS (Long Term Support) version.

Step 1: Initialize Your Project

Open your terminal and create a new directory for your project. Then, initialize a new package.json file.


# Create directory
mkdir my-11ty-site
cd my-11ty-site

# Initialize npm
npm init -y
            

Step 2: Install Eleventy

Now, install Eleventy as a development dependency. Using the --save-dev flag is best practice because Eleventy is only needed during the build process, not in the production environment.


npm install @11ty/eleventy --save-dev
            

Step 3: Create Your First Page

Let’s create a simple index.md file to see Eleventy in action.


---
title: My First Page
layout: main-layout.njk
---
# Welcome to Eleventy!

This is a static site generated with 11ty. It is incredibly fast.
            

Step 4: Run the Build

You can run Eleventy using npx. Use the --serve flag to start a local development server with hot-reloading.


npx @11ty/eleventy --serve
            

Eleventy will create a _site folder (the default output directory) and serve it at http://localhost:8080. If you open your browser, you will see your Markdown rendered as HTML.

Phase 2: Mastering the Eleventy Directory Structure

While Eleventy is zero-config, a professional project needs organization. As your project grows from a single page to a full-featured blog or documentation site, you should follow a structured approach. Here is a recommended structure for a scalable Eleventy project:


.
├── src/                    # Source files
│   ├── _data/              # Global data files (JSON/JS)
│   ├── _includes/          # Partial templates and layouts
│   ├── assets/             # Images, CSS, JS
│   ├── posts/              # Blog content
│   └── index.njk           # Homepage
├── .eleventy.js            # Configuration file
├── package.json
└── README.md
            

Configuring the Input and Output

To tell Eleventy to look into the src folder for content and output to a different directory (like public), we need to create a .eleventy.js configuration file in the root of our project.


// .eleventy.js
module.exports = function(eleventyConfig) {
  
  // Pass-through file copy (copy images/CSS to output)
  eleventyConfig.addPassthroughCopy("./src/assets");

  return {
    dir: {
      input: "src",
      output: "public",
      includes: "_includes",
      data: "_data"
    }
  };
};
            

Phase 3: Understanding Templating Engines

Eleventy’s superpower is its flexibility with templating. You are not forced to learn a specific language. However, for most developers, Nunjucks (inspired by Jinja2) and Liquid (created by Shopify) are the most popular choices.

Using Layouts

Layouts are templates that wrap your content. They usually live in the _includes directory. Let’s create a base layout in src/_includes/base.njk.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    <link rel="stylesheet" href="/assets/style.css">
</head>
<body>
    <header>
        <h1>My Site</h1>
    </header>

    <main>
        {{ content | safe }}
    </main>

    <footer>
        <p>© 2023 My Eleventy Site</p>
    </footer>
</body>
</html>
            

The {{ content | safe }} tag is vital. It tells Eleventy where to inject the content from your Markdown files. The | safe filter prevents Eleventy from escaping HTML tags, allowing your rendered Markdown to appear correctly.

Phase 4: Deep Dive into the Data Cascade

The “Data Cascade” is perhaps the most powerful concept in Eleventy. It determines how data is merged from different sources to be used in your templates. Eleventy looks for data in this order of priority (from highest to lowest):

  1. Computed Data: Data generated dynamically from other data.
  2. Front Matter in Template: Data defined at the top of an individual file.
  3. Template Data Files: A JSON or JS file with the same name as the template.
  4. Directory Data Files: Data files that apply to all templates in a directory.
  5. Global Data: Files in the _data folder.

Global Data Example

If you create src/_data/site.json, the data inside becomes available globally under the site variable.


{
  "name": "The Developer Blog",
  "url": "https://example.com",
  "author": "Jane Doe"
}
            

You can then access this in any template: <p>Copyright {{ site.author }}</p>.

Phase 5: Building a Real Blog with Collections

To build a blog, you need a list of posts. In Eleventy, this is handled through Collections. A collection is simply a group of content pieces that you can loop through.

Step 1: Tagging Your Content

In your src/posts/ folder, create several Markdown files. Add a tags: post attribute to the front matter of each.


---
title: My First Post
date: 2023-10-01
tags: post
---
This is the content of the first post.
            

Step 2: Creating a Blog List Page

In your src/blog.njk file, you can now loop through all items tagged with “post”.


---
layout: base.njk
title: Blog Posts
---
<h2>Latest Articles</h2>
<ul>
    {% for post in collections.post %}
        <li>
            <a href="{{ post.url }}">{{ post.data.title }}</a> - {{ post.date | dateFilter }}
        </li>
    {% endfor %}
</ul>
            

Note: The dateFilter is a custom filter we would define in our configuration to format the date correctly.

Phase 6: Advanced Customization: Filters and Shortcodes

To make your templates smarter, you can add JavaScript functions to your .eleventy.js file. These are called Filters (for modifying data) and Shortcodes (for generating reusable UI components).

Adding a Custom Date Filter


const { DateTime } = require("luxon");

module.exports = function(eleventyConfig) {
  // Date formatting filter
  eleventyConfig.addFilter("postDate", (dateObj) => {
    return DateTime.fromJSDate(dateObj).toLocaleString(DateTime.DATE_MED);
  });
};
            

Creating a Shortcode for a YouTube Embed

Shortcodes allow you to inject complex HTML with simple tags. This is great for responsive images or video embeds.


eleventyConfig.addShortcode("youtube", function(id) {
  return `<div class="video-wrapper">
            <iframe src="https://www.youtube.com/embed/${id}" frameborder="0" allowfullscreen></iframe>
          </div>`;
});
            

In your Markdown, you would use it like this: {% youtube "dQw4w9WgXcQ" %}.

Common Mistakes and How to Fix Them

Even experienced developers run into hurdles with Eleventy. Here are the most common pitfalls:

  • Forgot | safe: If your HTML tags are appearing as text on the screen, you likely forgot the | safe filter in your layout.
  • Pathing Issues: Remember that Eleventy doesn’t rewrite your asset paths automatically. If your CSS is in /assets/style.css, make sure you use a leading slash to ensure it works on sub-pages.
  • Front Matter Errors: YAML is very sensitive to indentation. Ensure your front matter is perfectly formatted or Eleventy will fail to build.
  • Not using Passthrough Copy: By default, Eleventy only processes template files. If your images or CSS aren’t showing up in the output folder, check that you’ve added addPassthroughCopy in your config.

Phase 7: Deployment Strategies

Since Eleventy generates standard HTML/CSS/JS, you can host it anywhere. Some of the best options include:

  • Netlify: Simply connect your GitHub repository, and Netlify will run npx @11ty/eleventy automatically on every push.
  • Vercel: Similar to Netlify, Vercel detects Eleventy projects and provides a seamless “zero-config” deployment.
  • GitHub Pages: You can use GitHub Actions to build your site and push the output to the gh-pages branch.

Summary and Key Takeaways

Eleventy represents a return to the fundamentals of the web: fast, accessible, and simple. Here is what we covered:

  • Eleventy is a Node.js-based SSG that outputs zero client-side JavaScript by default.
  • It supports a wide variety of templating languages, with Nunjucks being a top recommendation.
  • The Data Cascade allows for flexible and powerful management of variables across your site.
  • Collections are the primary way to organize and display lists of content like blogs or portfolios.
  • Custom Filters and Shortcodes let you extend Eleventy’s functionality with plain JavaScript.

Frequently Asked Questions (FAQ)

1. Is Eleventy better than Next.js?

It depends on the project. Next.js is better for complex web applications that require heavy user interaction and client-side state. Eleventy is significantly better for content-heavy sites (blogs, documentation, portfolios) where speed and SEO are the priorities.

2. Can I use React components in Eleventy?

Yes, but not natively in the way Gatsby does. You can use plugins like eleventy-plugin-react to render components to static HTML at build time, or you can use “Islands Architecture” frameworks like Astro if you need heavy component usage.

3. How do I handle CSS in Eleventy?

Eleventy doesn’t have a built-in CSS processor. Most developers use a simple addPassthroughCopy for plain CSS, or integrate an external build step with PostCSS, Sass, or Tailwind CSS using a task runner like npm scripts.

4. Does Eleventy support Image Optimization?

Yes! The official @11ty/eleventy-img plugin is world-class. It can automatically resize images, convert them to modern formats like WebP or Avif, and generate the necessary <picture> tags for responsive design.

This guide was designed to provide a comprehensive foundation for building with Eleventy. Start small, experiment with the data cascade, and watch your site’s performance soar.