I built this site with Eleventy (aka. 11ty), a modern static site generator. Why did I choose 11ty? How to set it up? Is it a good choice? Are there any gotchas? Read on!
As a long time web developer 👩🏼💻, I've never used any site generator before, not even WordPress... for the past 10+ years. Only vanilla JavaScript, frameworks & jQuery. The web dev scene is so diverse, right? 😄
(If you just want to see the code, here's the GitHub repo jec-11ty-starter.)
Why 11ty?
Honestly, I thought about rolling my own site from scratch using frameworks (Angular, Preact), because why not? 😆 Then I defeat myself with my own laziness.
Let's just pick a modern, shiny JAM stack or static site generator from the market!
The immediate "framework-ish" choices for me are Scully (Angular), Nuxt (Vue) and Gatsby (React). Nope, if I am going to use frameworks, I want to build from scratch, hah! (What weird logic 😂)
I recalled several people mentioning 11ty. Did a quick check on the official site, getting started and the documentation. Although the documentation looks a bit overwhelming, it seems legit and easy to start. One interesting & convincing discovery for me was that web.dev, Chrome Dev Summit 2019, ESLint, and Google V8 blog are built with 11ty!
Googling further, I found this step-by-step tutorial by Jon Keeping. I followed through the steps to build a basic blog. The tutorial gave a good overview on what 11ty provides. In short - minimal setup yet customizable through several out-of-the-box features.
As a developer that is familiar with Angular and Vue, the out-of-the-box features are similar to these frameworks' concept of filter, pipe, component, and directive. I feel comfortable with it.
Sorry WordPress, Hugo, Jekyll, and Hexo! I did not really do detailed research and comparison.
Building a personal blog is not a big life decision anyway. The tooling choice is personal. Pick a comfortable one and just go for it. If it fails, just dump it and pick another lah~
That being said, I like the 11ty experience so far!
My 11ty configuration
Although 11ty works with zero config out of the box, that's not what I want. The good news is we can customize that. I will go through a few of my settings.
Setup folder structure
This is the standard folder structure that I want my project to be.
- assets /* images, etc */
- src /* all source files */
- dist /* all files to be deployed */
- package.json
- .eleventy.js /* 11ty config file */
Out of the box, the 11ty configuration is different. We can customize that in the config file .eleventy.js
.
/* .eleventy.js */
module.exports = function (eleventyConfig) {
// set copy asset folder to dist
eleventyConfig.addPassthroughCopy('assets');
// set input and output folder
return {
dir: { input: 'src', output: 'dist' },
};
}
More configuration options can be found in the documentation.
Pick template languages
11ty supports quite a number of template languages, full list of languages available here. That being said, each language support and documentation varies, though. You can actually mix and use all of the template languages 😆, but let's deduce, pick, and focus.
I decided to go with:
- Nunjucks - a templating language open sourced by Mozilla, usually with file extension
.njk
. - Markdown - Markdown is everywhere, with file extension
.md
.
Another common option is Shopify's Liquid. After reading both docs, Nunjucks obviously has more advanced features (e.g. extends and macro). Honestly, I'm not sure if I need these features, but no harm going with that, given both languages' syntax are quite similar. By the way, you may also use EJS, PUG, HAML, Mustache, Handlebars
and more.
Let's update our configuration file to reflect that.
/* .eleventy.js */
module.exports = function (eleventyConfig) {
// set copy asset folder to dist
eleventyConfig.addPassthroughCopy('assets');
// set input and output folder
return {
dir: { input: 'src', output: 'dist' },
dataTemplateEngine: 'njk',
markdownTemplateEngine: 'njk'
};
}
Setting up NPM scripts
Let's take a look at my package.json
and see some of the helper scripts I have.
/* .package.json */
{
"name": "jec-fyi",
"scripts": {
"clean": "npx del dist",
"serve": "ELEVENTY_ENV=dev npx eleventy --serve",
"start": "npm run serve",
"build": "ELEVENTY_ENV=dev npx eleventy",
"build:prod": "ELEVENTY_ENV=prod npx eleventy",
"debug": "DEBUG=* npx eleventy"
},
"devDependencies": {
"@11ty/eleventy": "^0.10.0",
"del-cli": "^3.0.0"
}
}
A very clean start indeed, only two dev dependencies. 😆
Here're the explanation of the setup above:
- I always like my project to have a
start
script, to indicate the project starting point. - Setting up
clean
script to completely clear the output directory. - To build an 11ty project, the
eleventy
command is all you need. To run a local server, just add--serve
behind it. - In my script, I use
ELEVENTY_ENV
environment variable to indicate thedev
andprod
. I'll need this to enable / disable some of my code. It's entirely optional, and you may not need this. (Alternatively, you can use a.env
file or set it in your terminal / cmd)
Take note that the eleventy
command will not clean your output directory, but update the files within the directory instead. If you want a clean build every time, add the two scripts below:
/* .package.json */
{
...
"scripts": {
"prestart": "npm run clean",
"prebuild": "npm run clean",
}
}
I did not add the two scripts above because I'll run my build on my CI/CD server (will write about GitHub Actions
in a coming post), it would be a clean build every time. It didn't bother me that much in local (sometimes it does, heh).
Extra notes:
npx
is a built-in command in npm, allowing you to run local packages' commands. More details here- npm provides
pre
andpost
hook for commands. e.g. in our setup, when you runnpm start
, it will first runprestart
automatically.
Cool! Let's run npm install
then npm start
now. We are good to go!
Building first page
Let's start building a page to see if this works. Create an index.njk
file in the src
folder.
Assuming you are running the npm start
command, 11ty will watch your src
folder for changes.
<!-- index.njk -->
---
title: Home page
date: 2020-05-10
---
<html lang="en">
<head>
<title>{{ title }}</title>
</head>
<body>
{% set greeting = 'hello' %}
Yay, {{ greeting | upper }} world!
</body>
</html>
Now check the dist
folder, and you can see index.html
file is generated. Open browser and hit localhost:8080
. You should see Yay, HELLO world!
showing on screen with Home page
as the title.
From the example above, you can already see some of the features provided by 11ty and Nunjucks.
.njk
file will be rendered into.html
file indist
folder.- Nunjucks uses
{% %}
and{{ }}
syntax. - The top part enclosed with
---
is called Front Matter. It's a way for us to set and pass data around. (Will explore further in upcoming posts) upper
is something we refer to asfilter
. There are quite some number of built-in filters, check Nunjucks filters and 11ty fitlers. In the coming post, we will explore how to create our own filter! 😃
IDE Extensions & Settings
I am using VSCode. These are the few VSCode plugins that can help boost your development productivity. After all, who likes to keep typing {% %}
, hah.
- Nunjucks by ronnidc - code highlight for
.njk
files. - Nunjucks Snippets by luwenjiechn - provide snippets like
var
,njk
. - Nunjucks Template Formatter by Nanda Okitavera - right click
format
your.njk
files. - Prettier - Code formatter by Esben Petersen - generally, this is a good extension to format your codes - JavaScript, Markdown, CSS and more.
Gotcha:
There is a bug in the Nunjucks by ronnidc extension as of the time of writing. Syntax autocomplete (Emmet) doesn't work, refer to this GitHub issue. There is a workaround, add the below setting in your vscode settings.json
file manually (shortcut to open the file: CMD + OPTION + P
> Open Settings (JSON)
) and restart your IDE.
/* vscode settings.json */
"emmet.includeLanguages": {
"njk": "html",
"nunjucks": "html"
}
Alrighty, what's next?
That's all for now. We have successfully set up the project. That's how my site jec.fish was set up as well. In the coming posts, I plan to write about:
- Building Personal Static Site with Eleventy ✅
- Setting up GitHub Actions and Firebase Hosting ✅
- Customizing File Structure, URLs and Browsersync ✅
- Automating Image Optimization Workflow ✅
- Setting up SEO and Google Analytics ✅
- Minifying HTML, JavaScript, CSS - Automate Inline ✅
- How many favicons should you have in your site? ✅
- Creating Filters, Shortcodes and Plugins ✅
- Supporting Dark Mode in Your Website ✅
- and probably more!
Let me know if the above topics interest you. I highly recommend you to try out 11ty yourself! The development experience has been great so far.
Here's the GitHub repo for the code above: jec-11ty-starter. I'll update the repo whenever I write a new post.
Happy coding!
The jec.fish website itself isn't open source yet, but it will soon! Some housekeeping is needed before that. 😛
Have something to say? Leave me comments on Twitter 👇🏼
Follow my writing: @jecfish