Getting Started with Eleventy

Getting Started with Eleventy

These are my notes on the Egghead course Getting Started with Eleventy by Khaled Garbaya.

I’ve done a bit of extra research at a few steps to help me better understand what was going. These side notes are colored in blue and they have links to the original source.

You’ll find the final result of the project in this repository on Github.

I hope you learn a thing or two from these notes. Enjoy!

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>

.njk is the file extension for Nunjucks templating language. Double curly braces {{ ... }} denote an expression that are printed to the template output. We can use variables in them.

Everything between the two --- at the top of a file is called front matter. Front matter is metadata written in YAML syntax.

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.

The safe filter marks a variable as safe which means that the variable won’t be escaped. In other words, <h1> won’t be escaped to &lt;h1&gt;, which is what we want. Don’t use the safe filter when the content is coming from user input, as that will make your site vulnerable.

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.

Eleventy dev server watches for file changes and automatically updates your site. It uses Browsersync under the hood to automatically refresh your browser as well.

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.

Layouts documentation: https://www.11ty.dev/docs/layouts/

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.

Layouts are applied in a chain that stops at the last file without a layout property in the front matter. You can deduce what the end result is going to look like by following the layout property in the front matter. In our case:

1. Start at post.md and grab the content (everything after the front matter ---)
2. Go to the layout of post.md, namely mainlayout.njk, and replace the content variable with the content from previous step
3. Go to the layout of mainlayout.njk, namely mylayout.njk, and replace the content variable with the content from previous step

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>

Layout Chaining documentation: https://www.11ty.dev/docs/layout-chaining/

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.

{% ... %} is a statement in which you can use tags. We use the for tag to loop over an array.

Nunjucks outputs everything outside of expressions and statements as it is, including whitespace. With a minus sign (-) you tell the engine to strip any leading or trailing white space. By using two {%-, our HTML output comes out clean.

Go to the Nunjucks playground and play with the minus sign in all four places and note how the output changes.

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.

Collections documentation: https://www.11ty.dev/docs/collections/

Lesson 5: Create pages from data in Eleventy

Create a folder named _data in your root directory.

_data is a special folder in Eleventy. It’s where you place global data files. All *.json and module.exports values from *.js files in this directory will be added into a global data object available to all templates.

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 | slug }}/"
---
<p>Name: {{ pokemon.name }}</p>
<p>Power: {{ pokemon.power }}</p>

pagination instructs Eleventy to iterate over a data set and create a page for each element.

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. 🎉

Leave a Reply