Static site generators are very ร la mode right now and with the JAMStack becoming a more-than-viable alternative for many web projects these days, itโs no wonder!
JAMStack or not, static site generators (SSGs) offer some major advantages over more traditional CMSs, and when it comes to SSGs, there are plenty of options to choose from. Jekyll, Hugo, Gatsby, Next.jst, Sapper,โฆ Oh my!
I was recently shopping around to see what would be my best static site generator option for a project of mine called Spiral11. I was first leaning towards Gatsby because it packs some modern goodies like image optimization, but then I looked further at Eleventy and fell in love.
11ty is easy to use, doesnโt get in your way and spits out exactly what you put in, so thereโs no surprise or hidden code bloat. At its most basic, 11ty just compiles files it finds from your working directory into static HTML files. Plus, since itโs written in JavaScript, you gain access to the whole of npm
in terms of packages you can use in your project.
Letโs take a tour and see how it worksโฆ
Start by installing Eleventy globally on your machine using npm or Yarn:
# with npm
$ npm install -g @11ty/eleventy
# with Yarn
$ yarn global add @11ty/eleventy
Now you can run the eleventy
command in any directory that contains valid template files.
For example, say we have a directory called best-site-ever
, with an index.md
file in it:
## Chomp Chomp **Chomp** 🐊🐊🐊
You can now run eleventy
in that directory, youโll see that Eleventy creates a _site
directory with an index.html
file in it that contains what we expect:
<h2>Chomp Chomp <strong>Chomp</strong> 🐊🐊🐊</h2>
Speaking of template languages, you have plenty of options. You can use Markdown, Nunjucks, Liquid, Mustache,โฆ And you can mix and match, so you can have some files written in Liquid and some in Nunjucks and Eleventy will handle everything just fine.
The eleventy
command also accepts a few useful flags. For example:
That means that very often, when working locally, youโll want to serve and rebuild on changes with the following command:
$ eleventy --serve
With Eleventy youโre not only free to choose your favorite template language, but you can also choose your own directory structure.
Say we have another markdown file in our project, but this time itโs in two nested sub-directories:
One day *I will write* my 1st blog post!
Now if we run eleventy
, the output in _site
will look like this:
๐ _site/
index.html
๐ one/
๐ two/
๐ blog-post/
index.html
So youโll notice that the directory structure is kept, that the file name is used as the slug/URI and that Eleventy creates a directory for each outputted template with an index.html file within it which contains the HTML output.
What if we wanted our files organized in directories that are reflected differently in the final output? Easy, we can just specify the permalink for a particular template inside a front matter section at the top.
---
permalink: '/blog-post/'
---
One day *I will write* my 1st blog post!
Just run eleventy
again and youโll now see that now blog-post
appears at the root level in _site
. This way, specifying a permalink allows you full flexibility.
Speaking of front matter, you can put all sorts of metadata in it, which will then be available to layouts (more on that later). Itโs in the front matter, for example, that youโll specify things like the title, meta description/excerpt and tags for a post, and most of the keys can be named whatever youโd like.
Hereโs an example to illustrate:
---
title: "My first blog post 😊"
date: 2020-04-02
excerpt: "This post talks about how one day I'll write a 1st post."
permalink: '/blog-post/'
emotion: happy
tags:
- blog
- getting-started
---
One day *I will write* my 1st blog post!
I wonโt go too deep on the topic here, and I invite you to read the docs to learn more, but Eleventy uses the tags you provide in the front matter to populate collections, which can be iterated over in other templates like, say, category pages.
Thereโs also a special collection called all
which by default includes every single post. With the all
collection, you may end up with something like a sitemap that includes posts/pages you donโt want, so thereโs an easy way to opt out of having a post or page included in collections:
---
eleventyExcludeFromCollections: true
---
So far what weโve done is just output HTML from the markdown files weโve created. Most of the time though such markdown files should be wrapped in a layout to provide things like the boilerplate HTML, header, navigation bar, sidebar and footer.
By default layout templates should live in the _includes
directory.
Letโs create some sample layouts using Nunjucks syntax. One will be the default layout with our HTML boilerplate and the other one will be our blog layout:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }} | My Site</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
---
layout: default
---
<h1>{{ title }}</h1>
<div>
Published on {{ date }}
</div>
<article>
{{ content | safe }}
</article>
As you can see, a layout can call another layout and our layouts can access the data thatโs in the front matter of our regular template files.
We can use a layout by specifying it in the front matter of any of our content templates:
---
layout: blog.njk
title: "My first blog post 😊"
date: 2020-04-02
excerpt: "This post talks about how one day I'll write a 1st post."
---
One day *I will write* my 1st blog post!
So far weโve done everything without even touching a configuration file, and it goes to show the simplicity of using Eleventy. But as your website gains in complexity, youโll surely want to be able to set some configuration options. You can do that in an .eleventy.js
file at the root of your project.
Hereโs a sample configuration file which copies our static assets to the output directory and specifies a different output directory name (public
):
module.exports = eleventyConfig => {
// Copy our static assets to the output folder
eleventyConfig.addPassthroughCopy('css');
eleventyConfig.addPassthroughCopy('js');
eleventyConfig.addPassthroughCopy('images');
// Returning something from the configuration function is optional
return {
dir: {
output: 'public'
}
};
};
You can do all sorts of things in your config file like minifying the HTML output, using plugins and configuring shortcodes. Again, I invite you to look at the docs to learn more about what can be configured. But if you start to get overwhelmed at first, just remember that by default Eleventy doesnโt even need a config file and can do most of the heavy lifting without one.
So far weโve been creating a site from scratch to see how things work, but often youโll want to get started with a good base thatโs already configured and/or styled in a way that you like. You can browse through a list of 11ty starters here.
I personally really like the Skeleventy starter, which uses Tailwind CSS for styling and is configured with PurgeCSS to get rid of unused styles in production. If youโre starting a blog, the official Eleventy blog starter would also be a great place to start.
โจโจ Thatโs it for this brief introduction, but I invite you to learn more by checking out these resources:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the โreport an issueโ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!