Stephanie Eckles @5t3ph
11ty.Rocks • ModernCSS.dev • StyleStage.dev
⚡️
zero boilerplate client-side JavaScript
⚡️
includes Browsersync for hot-reload
⚡️
only an `index` required, config as needed
.eleventy.js
.eleventy.js
customize input/output dir, add plugins, filters, and shortcodes
⚡️
templating not required, add in as needed
special templates that can be used to wrap other content
---
title: Hello World
---
Welcome to my amazing 11ty website!
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ title }}</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
index.md
base.njk
---
title: Hello World
---
Welcome to my amazing 11ty website!
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ title }}</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
➡️
➡️
index.md
base.njk
---
title: News Post
layout: page.njk
---
A news posting.
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ title }}</title>
</head>
<body>
{{ content | safe }}
</body>
</html>
➡️
➡️
base.njk
---
layout: base.njk
---
<header>
<h1>{{ title }}</h1>
</header>
<article>
{{ content | safe }}
</article>
page.njk
---
title: Article
layout: page.njk
---
A blog article.
➡️
11ty.dev/docs/config/
override per file or in .eleventy.js
---
templateEngineOverride: njk, md
---
## Featured Person
{% for name in people | randomPerson %}
- {{ name }}
{% endfor %}
included in `_data/`, created as JSON or JS modules
module.exports = [
"Mary",
"Claire",
"Steph",
"Andy"
];
_data/people.js
## Featured Person
{% for name in people %}
- {{ name }}
{% endfor %}
➡️
fetch and format for your needs
const axios = require("axios");
module.exports = async () => {
const result = await axios.get("https://aws.random.cat/meow");
return result.data.file;
// Ex: https:\/\/purr.objects-us-east-1.dream.io\/i\/image1-4.jpg
};
fetched at build, not client-side
create `collections` for related content types using `tags`
can be added in
front matter
---
tags: post
# or
tags: ['post', 'webdev']
---
can be defined in directory data files
{
"layout": "post.njk",
"tags": "posts"
}
posts/posts.json
{
"layout": "post.njk",
"tags": "posts"
}
posts/posts.json
{% for post in collections.post -%}
- [{{ post.data.title }}]({{ post.url }})
{% endfor %}
[any template]
use anything in the Node/JS ecosystem at build time
<footer>
© {% year %} Acme Co.
</footer>
➡️
footer.njk
eleventyConfig.addShortcode("year",
() => `${new Date().getFullYear()}`
);
.eleventy.js
use `permalink` to change the file type and output location
Markdown
Nunjucks
Liquid
+7
➡️
.html
---
permalink: "feed/feed.xml"
eleventyExcludeFromCollections: true
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>{{ metadata.title }}</title>
<subtitle>{{ metadata.feed.subtitle }}</subtitle>
{% set absoluteUrl %}{{ metadata.feed.path | url | absoluteUrl(metadata.url) }}{% endset %}
<link href="{{ absoluteUrl }}" rel="self"/>
<link href="{{ metadata.url }}"/>
<updated>{{ collections.posts | rssLastUpdatedDate }}</updated>
<id>{{ metadata.feed.id }}</id>
<author>
<name>{{ metadata.author.name }}</name>
<email>{{ metadata.author.email }}</email>
</author>
{%- for post in collections.posts | reverse %}
{% set absolutePostUrl %}{{ post.url | url | absoluteUrl(metadata.url) }}{% endset %}
<entry>
<title>{{ post.data.title }}</title>
<link href="{{ absolutePostUrl }}"/>
<updated>{{ post.date | rssDate }}</updated>
<id>{{ absolutePostUrl }}</id>
<content type="html">{{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}</content>
</entry>
{%- endfor %}
</feed>
feed/feed.njk
[
{
"title":"Page A",
"slug":"page-a"
},
{
"title":"Page B",
"slug":"page-b"
},
{
"title":"Page C",
"slug":"page-c"
}
]
➡️
functions/pages.json
---
permalink: functions/pages.json
permalinkBypassOutputDir: true
eleventyExcludeFromCollections: true
---
[{% for pages in collections.pages %}
{
"title":"{{ pages.data.title | jsonTitle}}",
"slug":"{{ pages.data.title | slug}}"
}{% if forloop.last == false %},{% endif %}
{% endfor %}]
pagejson.njk
---
title: Page A
---
A nice page
➡️
---
title: Page B
---
A lovely page
---
title: Page C
---
The best page
@eleven_ty
➡️
eleventyConfig.addNunjucksAsyncFilter("emailHtml", (raw, callback) => {
if (meta.environment === "prod") {
callback(null, juice(raw));
} else {
callback(null, raw);
}
});
.eleventy.js
/*
* Sass styling
*/
---
subject: Hello New Subscriber!
heroImg: http://site.com/image.png
headline: Welcome to 11ty Rocks!
# ... and more
---
➡️
➡️
⚙️
aka "Exploiting layout functionality"
➡️
{%- set componentName = page.fileSlug %}
{%- set componentClass = page.fileSlug | createClass %}
{%- set componentScript %}components/{{componentName}}/script.js{% endset %}
{%- set componentCss %}components/{{componentName}}/style.css{% endset -%}
export class {{ componentClass }} extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
const { shadowRoot } = this;
shadowRoot.innerHTML = `
<style>
* {
box-sizing: border-box;
}
{% include componentCss %}
</style>
{{ content | safe}}
`;
{% include componentScript %}
}
}
window.customElements.define("{{ componentName }}", {{ componentClass }});
_includes/component.njk
<h1 class="hello-world">
Hello World
</h1>
const hw = shadowRoot.querySelector(".hello-world");
setTimeout(() => {
hw.classList.add('hello-world__visible');
}, 1000);
➕
.hello-world {
color: var(--hw-color, white);
opacity: 0;
transition: opacity 180ms ease-in;
}
.hello-world__visible {
opacity: 1;
}
➕
components/hello-world.njk
_includes/components/hello-world/script.js
_includes/components/hello-world/style.css
🎩
🎩
🎩
Generator's Example Worklet
🎩
class HoudiniExample {
static get inputProperties() {
return [
"--houdiniExampleWidth",
"--houdiniExampleHeight",
"--houdiniExampleX",
"--houdiniExampleY",
"--houdiniExampleColor",
];
}
paint(ctx, size, properties) {
const width =
parseInt(properties.get("--houdiniExampleWidth")) || size.width;
const height =
parseInt(properties.get("--houdiniExampleHeight")) || size.height;
const x = parseInt(properties.get("--houdiniExampleX")) || 0;
const y = parseInt(properties.get("--houdiniExampleY")) || 0;
const color = String(properties.get("--houdiniExampleColor")) || "purple";
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
}
registerPaint("houdiniExample", HoudiniExample);
worklet.js
🎩
ButtonBuddy.dev
💜
`Static Site` !== `No Modern Client-Side JS`
learn new things
get feedback
grow your network
meet new awesome web makers
Stephanie Eckles @5t3ph
11ty.Rocks • ModernCSS.dev • StyleStage.dev