Skip to content

Getting Started with Eleventy

5 min read

Lesson 1: Bootstrap an Eleventy project

Install Eleventy with npm i @11ty/eleventy. Add two scripts in package.json:

"scripts": {
  "start": "eleventy --serve",
  "build": "eleventy"
}
  • npm start — start a dev server to preview the site
  • npm run build — build site

Create an index.html file:

<h1>Hello World</h1>

Start dev server with npm start and go to localhost:8080.

Eleventy supports Markdown out of the box. Rename index.html to index.md and change the contents to:

# Hello World

And it works! 🥳

Lesson 2: Use Eleventy layouts

Create an _includes folder at the root of the project. Inside the folder, add a file called mylayout.njk:

---
title: My Website
---
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ title }}</title>
</head>

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

</html>

Eleventy makes the contents of a file that uses this layout available through the content variable. The pipe operator (|) is then used to pass the content through a filter function.

We pass the content through the safe filter.

Create a file at the root of the project with the name post.md:

---
layout: mylayout.njk
---

## My First Post

In the front matter of this page, we specify which layout it uses with the layout property.

Go to localhost:8080/post and you will see the new page.

The title of the page is "My Website", which comes from the title property in the front matter of the layout file. You can override this on per page basis by adding a title property to the front matter of a particular page that uses that layout:

---
layout: mylayout.njk
title: My First Post
---

## My First Post

You'll see the title has been updated.

Lesson 3: Use Layout Chaining in Eleventy

Create a new file mainlayout.njk in the _includes folder:

---
layout: mylayout.njk
---
<main style="color: red">
  {{ content | safe }}
</main>

A layout that uses another layout! This is called Layout Chaining.

Go back to post.md and change the layout property to use the new layout:

---
layout: mainlayout.njk
title: My First Post
---

## My First Post

In your browser, you'll see that the title is now red.

You're basically constructing the HTML page inside out. The end result looks like this:

<!-- mylayout.njk -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My First Post</title>
  </head>
  <body>
    <!-- mainlayout.njk -->
    <main style="color: red">
      <!-- post.md -->
      <h2>My First Post</h2>
    </main>
  </body>
</html>

Lesson 4: Use Collections in Eleventy

Let's add a tags property to post.md:

---
layout: mainlayout.njk
title: My First Post
tags: post
---

## My First Post

Rename index.md to index.njk and change its contents to:

---
layout: mylayout.njk
---
<h1> All Posts </h1>
<ul>
{%- for post in collections.post %}
  <li>
    <a href={{ post.url }}>{{ post.data.title }}</a>
  </li>
{%- endfor %}
</ul>

collections is a variable provided to you by Eleventy. Each tag available in your project will be a property on the object containing an array of posts/pages with that tag. In this case, we access the posts in the post tag with collections.post.

In the browser at localhost:8080, you will see the titles of all post that have the post tag. Each title is a link that leads you to the post page.

Lesson 5: Create pages from data in Eleventy

Create a folder named _data in your root directory.

Inside the folder, create a file pokemons.json:

[
  {
    "name": "Pikachu",
    "power": "Electricity"
  },
  {
    "name": "Charizard",
    "power": "Fire"
  }
]

In the root of the project, add another file named pokemon-page.njk:

---
pagination:
  data: pokemons
  size: 1
  alias: pokemon
permalink: "pokemons/{{ pokemon.name | slugify }}/"
---
<p>Name: {{ pokemon.name }}</p>
<p>Power: {{ pokemon.power }}</p>

We use pokemons as the data source, which corresponds with the file name inside the _data folder we created earlier.

size is the amount of posts per page, in our case 1. alias is how we want to refer to an individual element inside the data set. In our case it's a pokemon.

We then use this alias to construct a permalink for each page by passing pokemon.name through a slug filter.

After you save the file, you'll notice in the console Eleventy is creating pages for each pokemon:

Writing _site/pokemons/pikachu/index.html from ./pokemonpage.njk
Writing _site/pokemons/charizard/index.html from ./pokemon-page.njk

Navigate to localhost:8080/pokemons/charizard and localhost:8080/pokemons/pikachu. 🎉

Hungry for knowledge? 🧠

My curiosity has led me to the farthest corners on the web — from reading documentation hours on end, to diving deep into a repository wanting to figure out how a feature really works.

The beautiful thing about learning is that no one can take it away from you

Knowledge is best shared. Whenever I read a book, watch a talk, or go through a course, I write down my notes so devs like you can learn from them.

Drop your email below and I'll make sure to send nuggets of gold your way. 🍬

No spam! 🙅🏻‍♀️ Unsubscribe at any time.

You might also like

Why Your calc() Function in CSS Might Be Broken

You've fiddled with calc() a dozen times. Learn the common mistake devs make with math in CSS and finally fix your issue.
Read article

A Memory Trick To Remember When to Use for...of vs for...in

When should you use for...of vs for...in? This neat memory trick has saved me countless Google searches.
Read article

Understanding "Property of Undefined" TypeError in JavaScript

Demystifying the often-misleading "TypeError: can't access property of undefined" in JavaScript.
Read article