Getting Started With 11ty

Part 1 - Setting up a project, layouts, includes and assets.

Christian Mejlak

28 Sep 2020, in Jamstack

Getting Started With 11ty

11ty is a powerful, flexible, extensible and fast static site generator. It is highly configurable, for example it allows you to use different template engines. This is all great, however I remember when I first started playing with it, I had been using Jekyll for a few years. And I stumbled a bit.

This is the first part of a series. In this post I want us to get a basic working example. Here’s what we’ll go through:

  • Setting up a project
  • Using layouts and includes
  • Working with assets - images, CSS, JS

Building an 11ty site

Setting up the project

The first thing is to create a directory where our project will live. Open your project in the terminal. Create a folder my-eleventy-site.

# inside my-eleventy-site/
npm init -y

Next we’ll install eleventy as a dev dependecy.

npm i -D @11ty/eleventy

Next we’ll create a couple of folders in the root of our project. Create the following folders:

  • _includes/
  • _layouts/
  • assets/

_includes will hold all our reusable parts. _layouts as the name suggests will hold all of our layouts. assets is where we’ll place all of our CSS, JS and images.

Now create a file called .eleventy.js. This is where all eleventy configuration goes.

module.exports = function (config) {
    return {
        dir: {
            layouts: "_layouts",
        },
        htmlTemplateEngine: "liquid",
        markdownTemplateEngine: "liquid",
    };
};

Let me explain the above code. The dir object has a property layouts. This tells eleventy where to look for layouts. By default it will look in the _includes, which is where our reusable parts live. But I like to keep them separate.

The other two properties htmlTemplateEngine and markdownTemplateEngine, tell eleventy to process our html and markdown files using liquid.

That’s some configuration out of the way, now let’s create our first file.

index.html

Create an index.html file in the root of the project.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>My first 11ty site</title>
    </head>
    <body>
        This site is to be built with 11ty
    </body>
</html>

Now head over the terminal and run

npx @11ty/eleventy

This should create a folder in your project _site. In it, you should have an index.html. It’s basically a copy of the one we have created.

Now let’s make it a bit more interesting.

Using layouts

Layouts are essential, imagine having to write the markup for the header and footer on every single page. It would be a nightmare to maintain such a site.

Create a base.html file inside the _layouts folder, and place the content below.

<!-- _layouts/base.html-->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <!-- when extending this layout content will be placed here -->
        {{ content }}
    </body>
</html>

Basically I’ve just copied the index.html content. With one difference. Inside the body I only have the liquid “content” tag. Now let’s head back over to the index.html file and make the following edits.

---
layout: base.html
---
11ty is Awesome!

What we’re doing here, is telling eleventy to use the base.html as the layout and the content underneath the frontmatter is to be placed in the “content” placeholder.

In your terminal run npx @11ty/eleventy. In your _site directory you should have an index.html file, with the content from base.html and index.html merged.

If you’ve made it so far let’s take it a step further.

Front matter

We’ve seen frontmatter in action above, when we made use of layouts.

What is front matter?

Front matter must be the first item in the file. It allows us to set variables, and give instructions to eleventy. Eleventy allows us to declare front matter in JSON, JavaScript, YAML and you can also add your own format. I’ll be using YAML, coming from Jekyll that’s an obvious choice.

Using front matter.

To open a front matter block you add three dashes --- and another 3 dashes to close it.

---
layouts: base.html
---

Now let’s add a title to the page and have it render in the layout. Yes you can pass data from files to layouts, because of the way data cascades in eleventy. So in index.html add the following.

---
layouts: base.html
title: Hello from index.html
---

Now let’s open _layouts/base.html and edit the title tag.

<!-- _layouts/base.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- this is not coming from the page using this layout -->
    <title>{{ title }}</title>
</head>
<body>
    <!-- when extending this layout content will be placed here -->
    {{ content }}

</body>
</html

Now let’s build the site and check out _site/index.html.

Front matter also allows to create lists, which we can then loop over in the template. Here’s an example.

---
layout: base.html
title: Hello from index
fruits:
 - apple
 - banana
 - pineapple
---

List all the fruits
<ul>
    {% for fruit in fruits %}
        <li>{{ fruit }}</li>
    {% endfor %}
</ul>

Includes

Includes allow us to reuse pieces of code. We’ll be adding a basic header to our site. Now in our example we only have one page, but in a real project you’d probably have more than that.

So inside of the _includes/ folder let’s create a header.liquid file.

<!-- header.liquid -->

<nav>
    <ul>
        <li>
            <a href="/">Home</a>
        </li>
        <li>
            <a href="/about">About</a>
        </li>
    </ul>
</nav>

Now in our _layouts/base.liquid let’s add the header, just after the opening <body> tag.

<!-- _layouts/base.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- this is not coming from the page using this layout -->
    <title>{{ title }}</title>
</head>
<body>
    {% include header %}
    {{ content }}

</body>
</html

Build the site and now all your pages should contain the header.

npx @11ty/elevent

This is really powerful, as it allows you to break the page into reusable parts.

Static assets

Eleventy will not copy CSS, JavaScript and image files by default. It will simply ignore them. Let me show you what I mean. Inside of the assets/ folder add a style.css file and add the following styling.

html {
    color: red; // some wonderful styling I know
}

Now let’s open our _layouts/base.liquid and add the style tag.

<!-- base.liquid -->

<link rel="stylesheet" href="/assets/style.css" />

Build the site

npx @11ty/eleventy

As you’ll see nothing changed. And if you open your _site folder which eleventy generates, our CSS file is nowhere to be found. This is because we need to tell eleventy to create a copy of our assets and pass it to the _site when building. Fortunately this is quite easy to do.

Open .eleventy.js file, and add this line.

module.exports = function (config) {
    // we simply tell eleventy to pass a copy of our assets folder
    config.addPassthroughCopy("./assets");

    return {
        // setup from before here
    };
};

Save, and let’s rebuild the site.

npx @11ty/eleventy

Now all should be working, and everything you add to the assets folder will be made available.

Conclusion

This being the first post of a series, we’ve seen how to get started and basic setup. Next we’ll look how to make use of collections, we’ll be creating a basic blog, and see how we can make our includes more dynamic. So keep an eye open for the next one.

other posts

Atomic CSS, and the rise of Tailwind CSS

Christian Mejlak

by Christian Mejlak in 17 Feb 2020

CSS might not be the hardest thing to write. But for anyone who's worked with it for a while, knows there are some complexities. Can atomic CSS help?

continue reading

AlpineJS. Not another JavaScript Framework

Christian Mejlak

by Christian Mejlak in 03 Feb 2020

A minimal JS framework which borrows from Vue.

continue reading