This article is the first in a series where you'll learn the basics of Eleventy by creating a mini-blog. In this article, we'll start by seeing how to initialize a new project from scratch. In the next one, we'll create the sources for our mini-blog.
What is Eleventy?
Eleventy is a static site generator (SSG). A static site is one where the visual rendering of pages is done before the site is published on the server. The site's HTML pages are all ready to be sent to the browser as soon as someone navigates to their URLs and don't need to be dynamically generated with each request.
Tip
Before going further, if you're unfamiliar with the concept of a static site, I highly recommend reading this article, which explains when to use one and the basic principles of building a static site using a generator.
Additionally, if you want to know how Eleventy compares to other well-known generators like Hugo, Gatsby, Astro, or Jekyll, take a look at this short article
I'll now assume you know what a static site is and understand the advantages of Eleventy as an SSG. So, let’s dive into the code and see how to set up an Eleventy project in practice.
Starting from a Starter Project... or Not
The Starter Projects page on Eleventy's website lists 170 starter projects. Each represents a basic site with its own page layouts, styles, and features. Starting with a project that matches your needs can save a lot of time compared to creating one from scratch.
However, finding the right starter project is far from easy for three reasons:
- The project listing page only provides a very brief description of each project and offers no way to filter the list based on various criteria.
- Some projects have a demo site, but it sometimes doesn’t show much.
- Many projects haven’t been maintained as Eleventy has evolved and are now completely outdated or require significant updates.
In practice, this list is hard to use, and you can waste a lot of time jumping from one project to another.
Warning
Moreover, choosing a starter project without being sure it fits your needs might end up costing you even more time.
My personal experience is this:
When creating my blog, I started with the official eleventy-base-blog starter project. But on one hand, this project isn’t natively multilingual, and on the other, once I became more proficient with Eleventy, I realized some of its technical choices didn’t align with what I wanted. As a result, my site’s current code looks nothing like the starter project. If I had to do it again, I’d start from scratch without hesitation.
In fact, adapting the code of an existing starter project can sometimes take longer than starting from zero, especially with the help of AI. Plus, there’s a significant risk of leaving behind dead code (like unused filters and styles) that will only confuse you later.
Tip
So, unless you’re in a hurry and not too picky, my advice would be to only use a starter project if it truly matches what you want to do. An alternative is to start a blank project and draw inspiration from other projects’ code to implement certain things more quickly.
In the rest of this article, I’ll show you how to create a project from scratch. If you’d like to try a starter project downloaded from Eleventy’s site, just unzip the file where you want it and run the npm install
command we’ll see later.
Installing the Necessary Tools
Eleventy relies on Node.js to generate the site. Before creating a project, you’ll need to install Node.js on your machine if you haven’t already. You can download it from Node’s official website. The npm package manager is installed automatically with Node. It will be very useful for adding plugins and running the site generation.
Note
Node.js is only used during the site generation phase, not for the site’s production operation. A static site doesn’t need Node.js or any server framework to function.
You’ll also need a code editor, of course. I’ll use VS Code as an example, but you can use another one.
I also recommend the Better Nunjucks extension, which adds syntax highlighting and snippets for the Nunjucks templating language we’ll use in our project.
Tip
The vscode-icons extension is also very handy for navigating the project’s many files more easily, as it assigns specific icons and colors to each file type. This makes it much easier to distinguish Nunjucks (HTML), Markdown, CSS, and JavaScript files.
Creating the Project
To create a new project, follow these steps:
- Create a folder for the project wherever you want on your disk.
- Open this folder in VS Code (File \ Open Folder).
- Open a terminal (Terminal \ New Terminal or
CTRL+SHIFT+ù
). The prompt should point to the open folder. Run the following commands one by one:
npm init -y
npm pkg set type="module"
npm install @11ty/eleventy
- The first command creates a package.json file that will reference all the npm packages (= modules) needed for the project.
- The second specifies that we’ll use the ECMAScript Modules standard instead of CommonJS for referencing and using modules. In practice, this allows us to use the syntax
import ... from "module_name";
. - The third installs the Eleventy npm package and all its dependencies. It creates a node_modules folder containing over 1,700 files, but they only take up about 16 MB in total. You’ll never need to modify this folder manually.
Here’s what the package.json file looks like for a project folder named "demo":
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@11ty/eleventy": "^3.1.2"
}
}
We can see that the Eleventy package is automatically referenced in the "dependencies" property. You can change the project name and add a description if you like. But the most important thing is to add build commands.
Adding Build Commands
These are the commands that will allow you to launch the site generation, i.e., generate the output files from the input files (the project’s sources). To do this, modify the "scripts" section with the following:
"scripts": {
"build": "npx @11ty/eleventy",
"start": "npx @11ty/eleventy --serve --quiet",
}
The first command runs Eleventy to generate the site from the sources. It’s mainly used to verify that all source files are correct and that the site builds properly, without launching it.
The second command does the same thing but also launches the HTTP server built into Eleventy and opens the site’s index page in the default browser. This allows you to check the site’s visual appearance.
Note
As you can see, Eleventy is self-contained for building and running a site. This integration allows it to build a site much faster than other static site generators that rely on external tools like Webpack.
At this point, we have everything we need to start developing the site by adding source files.
Creating a Configuration File
An Eleventy project must include an eleventy.config.js file that describes its configuration. You can create this file now at the project’s root.
This file is, in a way, the project’s core, centralizing all its configuration. We’ll expand it as we build our example project, but we need it now to declare and configure plugins.
Adding Plugins
Zach Leatherman, Eleventy’s creator, wanted from the start to make Eleventy a modular framework by externalizing advanced features into plugins rather than integrating them into the base package. This keeps the framework’s core lightweight, and everyone can add the plugins they need. Here, we’ll see how to add the @11ty/eleventy-img
plugin, which is almost essential for easily managing a site’s images (a complex challenge without the right tools).
Note: Installing the Eleventy package also installs a few default plugins. For these, the first two steps below aren’t necessary.
To add and configure a plugin, follow these 4 steps:
- Reference the plugin’s package in the package.json file:
"dependencies": {
"@11ty/eleventy": "^3.1.2",
"@11ty/eleventy-img": "^6.0.4"
}
Note: To find the latest version of the package, you can search for it in the official npm package repository. At the time of writing, it’s version 6.0.4. The caret (^) before the 6 means you can automatically receive package updates as long as the major version number (6) doesn’t change.
-
Download the plugin by running the
npm install
command in the terminal. This command reads the package.json file and downloads the referenced packages into the node_modules folder. -
Import the plugin into the configuration file eleventy.config.js that we created earlier:
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
Here, we use the ESM syntax to import the plugin into an object named eleventyImageTransformPlugin
(the name is up to you). This object gives us access to the plugin’s configuration.
- Configure the plugin by adding the necessary code to the configuration file. Here’s an annotated example of the configuration for our image management plugin:
// Import functions of external libraries
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
import path from "node:path";
export default async function (eleventyConfig) {
// --- ADD PLUGINS and configure it ---
// Config for the @11ty/eleventy-img plugin
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
// Output images format
formats: ["avif"],
// Preserves original image widths and does not create other sizes
widths: ["auto"],
// Output files naming
filenameFormat: function (id, src, width, format, options) {
// extracts the file name, without extension, from its full path
const name = path.basename(src, path.extname(src));
return `${name}.${format}`;
},
// Lazy loading of images
htmlOptions: {
imgAttributes: {
loading: "lazy",
decoding: "async",
}
},
// Options for the Sharp library used by the plugin to encode images in AVIF format
sharpOptions: {
animated: true,
},
sharpAvifOptions: {
quality: 60,
effort: 6,
chromaSubsampling: "4:2:0",
bitdepth: 8
},
});
}
Note: Many plugins require much simpler and shorter configuration than this.
The configuration above automatically generates images in AVIF format from source files in PNG or JPG format. AVIF is a modern format widely supported by recent browsers; it significantly reduces image weight, improving page load times, user experience, and natural SEO.
Additionally, the plugin also implements lazy loading for images, allowing users to start reading content without waiting for all images to finish downloading.
We could also ask the plugin to generate a smaller version of each image to further optimize load times on mobile. But this is only really useful for heavy or numerous images. Keeping a single image size simplifies things. This is the choice I made for my own blog, in fact.
By default, generated images have alphanumeric code names. But you can specify a more explicit naming convention using the filenameFormat
parameter. Here, we simply take the original image’s name and change its extension to avif.
Conclusion
This article has shown you how to set up an Eleventy project from scratch and how to add plugins.
We’ve now prepared the groundwork for the next steps, where we’ll create our mini-blog. I’ll see you in the next article, where you’ll learn how to create page templates, organize project files, and expand the configuration.
Let me know in the comments if this article helped you and if you have any questions.