Skip to content

Commit bff655c

Browse files
authored
Merge pull request #184 from 11ty/v9
Eleventy Base Blog v9 (using Eleventy v3 and ESM)
2 parents 231c29b + 9b0cb97 commit bff655c

36 files changed

+402
-431
lines changed

.nvmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16
1+
20

README.md

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# eleventy-base-blog v8
1+
# eleventy-base-blog v9
22

33
A starter repository showing how to build a blog with the [Eleventy](https://www.11ty.dev/) site generator (using the [v2.0 release](https://www.11ty.dev/blog/eleventy-v2/)).
44

@@ -45,36 +45,35 @@ Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the
4545

4646
## Features
4747

48-
- Using [Eleventy v2.0](https://www.11ty.dev/blog/eleventy-v2/) with zero-JavaScript output.
48+
- Using [Eleventy v3](https://github.com/11ty/eleventy/releases/tag/v3.0.0) with zero-JavaScript output.
4949
- Content is exclusively pre-rendered (this is a static site).
5050
- Can easily [deploy to a subfolder without changing any content](https://www.11ty.dev/docs/plugins/html-base/)
5151
- All URLs are decoupled from the content’s location on the file system.
5252
- Configure templates via the [Eleventy Data Cascade](https://www.11ty.dev/docs/data-cascade/)
5353
- **Performance focused**: four-hundos Lighthouse score out of the box!
54-
- [View the Lighthouse report for the latest build](https://eleventy-base-blog.netlify.app/reports/lighthouse/) courtesy of the [Netlify Lighthouse plugin](https://github.com/netlify/netlify-plugin-lighthouse).
5554
- _0 Cumulative Layout Shift_
5655
- _0ms Total Blocking Time_
5756
- Local development live reload provided by [Eleventy Dev Server](https://www.11ty.dev/docs/dev-server/).
5857
- Content-driven [navigation menu](https://www.11ty.dev/docs/plugins/navigation/)
59-
- [Image optimization](https://www.11ty.dev/docs/plugins/image/) via the `{% image %}` shortcode.
58+
- Fully automated [Image optimization](https://www.11ty.dev/docs/plugins/image/)
6059
- Zero-JavaScript output.
6160
- Support for modern image formats automatically (e.g. AVIF and WebP)
61+
- Processes images on-request during `--serve` for speedy local builds.
6262
- Prefers `<img>` markup if possible (single image format) but switches automatically to `<picture>` for multiple image formats.
6363
- Automated `<picture>` syntax markup with `srcset` and optional `sizes`
6464
- Includes `width`/`height` attributes to avoid [content layout shift](https://web.dev/cls/).
6565
- Includes `loading="lazy"` for native lazy loading without JavaScript.
6666
- Includes [`decoding="async"`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding)
6767
- Images can be co-located with blog post files.
68-
- View the [Image plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.images.js)
6968
- Per page CSS bundles [via `eleventy-plugin-bundle`](https://github.com/11ty/eleventy-plugin-bundle).
7069
- Built-in [syntax highlighter](https://www.11ty.dev/docs/plugins/syntaxhighlight/) (zero-JavaScript output).
70+
- Draft content: use `draft: true` to mark any template as a draft. Drafts are **only** included during `--serve`/`--watch` and are excluded from full builds. This is driven by the `addPreprocessor` configuration API in `eleventy.config.js`. Schema validator will show an error if non-boolean value is set in data cascade.
7171
- Blog Posts
72-
- Draft posts: use `draft: true` to mark a blog post as a draft. Drafts are **only** included during `--serve`/`--watch` and are excluded from full builds. View the [Drafts plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.drafts.js).
7372
- Automated next/previous links
7473
- Accessible deep links to headings
7574
- Generated Pages
7675
- Home, Archive, and About pages.
77-
- [Feeds for Atom and JSON](https://www.11ty.dev/docs/plugins/rss/)
76+
- [Atom feed included (with easy one-line swap to use RSS or JSON](https://www.11ty.dev/docs/plugins/rss/)
7877
- `sitemap.xml`
7978
- Zero-maintenance tag pages ([View on the Demo](https://eleventy-base-blog.netlify.app/tags/))
8079
- Content not found (404) page
@@ -83,20 +82,19 @@ Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the
8382

8483
- [Netlify](https://eleventy-base-blog.netlify.app/)
8584
- [Vercel](https://demo-base-blog.11ty.dev/)
86-
- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
8785
- [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
8886
- [Cloudflare Pages](https://eleventy-base-blog-d2a.pages.dev/)
87+
- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
8988

9089
## Deploy this to your own site
9190

9291
Deploy this Eleventy site in just a few clicks on these services:
9392

93+
- Read more about [Deploying an Eleventy project](https://www.11ty.dev/docs/deployment/) to the web.
9494
- [Deploy this to **Netlify**](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)
9595
- [Deploy this to **Vercel**](https://vercel.com/import/project?template=11ty%2Feleventy-base-blog)
9696
- Look in `.github/workflows/gh-pages.yml.sample` for information on Deploying to **GitHub Pages**.
9797
- [Try it out on **Stackblitz**](https://stackblitz.com/github/11ty/eleventy-base-blog)
98-
- If you run Eleventy locally you can drag your `_site` folder to [`netlify.com/drop`](https://netlify.com/drop) to upload it without using `git`.
99-
- Read more about [Deploying an Eleventy project](https://www.11ty.dev/docs/deployment/) to the web.
10098

10199
### Implementation Notes
102100

@@ -105,9 +103,6 @@ Deploy this Eleventy site in just a few clicks on these services:
105103
- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
106104
- Content can be in _any template format_ (blog posts needn’t exclusively be markdown, for example). Configure your project’s supported templates in `eleventy.config.js` -> `templateFormats`.
107105
- The `public` folder in your input directory will be copied to the output folder (via `addPassthroughCopy` in the `eleventy.config.js` file). This means `./public/css/*` will live at `./_site/css/*` after your build completes.
108-
- Provides two content feeds:
109-
- `content/feed/feed.njk`
110-
- `content/feed/json.njk`
111106
- This project uses three [Eleventy Layouts](https://www.11ty.dev/docs/layouts/):
112107
- `_includes/layouts/base.njk`: the top level HTML structure
113108
- `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)

_config/filters.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { DateTime } from "luxon";
2+
3+
export default function(eleventyConfig) {
4+
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
5+
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
6+
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
7+
});
8+
9+
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
10+
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
11+
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat('yyyy-LL-dd');
12+
});
13+
14+
// Get the first `n` elements of a collection.
15+
eleventyConfig.addFilter("head", (array, n) => {
16+
if(!Array.isArray(array) || array.length === 0) {
17+
return [];
18+
}
19+
if( n < 0 ) {
20+
return array.slice(n);
21+
}
22+
23+
return array.slice(0, n);
24+
});
25+
26+
// Return the smallest number argument
27+
eleventyConfig.addFilter("min", (...numbers) => {
28+
return Math.min.apply(null, numbers);
29+
});
30+
31+
// Return the keys used in an object
32+
eleventyConfig.addFilter("getKeys", target => {
33+
return Object.keys(target);
34+
});
35+
36+
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
37+
return (tags || []).filter(tag => ["all", "posts"].indexOf(tag) === -1);
38+
});
39+
40+
};

_data/eleventyDataSchema.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { z } from "zod";
2+
import { fromZodError } from 'zod-validation-error';
3+
4+
export default function(data) {
5+
// Draft content, validate `draft` front matter
6+
let result = z.object({
7+
draft: z.boolean().or(z.undefined()),
8+
}).safeParse(data);
9+
10+
if(result.error) {
11+
throw fromZodError(result.error);
12+
}
13+
}

_data/metadata.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
module.exports = {
2-
title: "Eleventy Base Blog v8",
1+
export default {
2+
title: "Eleventy Base Blog v9",
33
url: "https://example.com/",
44
language: "en",
55
description: "I am writing about my experiences as a naval navel-gazer.",

_includes/layouts/base.njk

+22-14
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,36 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>{{ title or metadata.title }}</title>
77
<meta name="description" content="{{ description or metadata.description }}">
8-
9-
{#- Atom and JSON feeds included by default #}
10-
<link rel="alternate" href="/feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
11-
<link rel="alternate" href="/feed/feed.json" type="application/json" title="{{ metadata.title }}">
8+
<link rel="alternate" href="feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
129

1310
{#- Uncomment this if you’d like folks to know that you used Eleventy to build your site! #}
1411
{#- <meta name="generator" content="{{ eleventy.generator }}"> #}
1512

1613
{#-
17-
CSS bundles are provided via the `eleventy-plugin-bundle` plugin:
18-
1. You can add to them using `{% css %}`
19-
2. You can get from them using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
20-
3. You can do the same for JS: {% js %}{% endjs %} and <script>{% getBundle "js" %}</script>
21-
4. Learn more: https://github.com/11ty/eleventy-plugin-bundle
14+
Plain-text bundles are provided via the `eleventy-plugin-bundle` plugin:
15+
1. CSS:
16+
* Add to a per-page bundle using `{% css %}{% endcss %}`
17+
* Retrieve bundle content using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
18+
2. Or for JavaScript:
19+
* Add to a per-page bundle using `{% js %}{% endjs %}`
20+
* Retrieve via `{% getBundle "js" %}` or `{% getBundleFileUrl "js" %}`
21+
3. Learn more: https://github.com/11ty/eleventy-plugin-bundle
2222
#}
2323

2424
{#- Add an arbitrary string to the bundle #}
25-
{%- css %}* { box-sizing: border-box; }{% endcss %}
25+
{%- css %}/* This is an arbitrary CSS string added to the bundle */{% endcss %}
2626
{#- Add the contents of a file to the bundle #}
2727
{%- css %}{% include "public/css/index.css" %}{% endcss %}
28-
{#- Or add from node_modules #}
28+
{#- Or you can add from node_modules #}
2929
{# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
3030

31-
{#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
31+
{#- Render the CSS bundle using inlined CSS (for the fastest site performance in production) #}
3232
<style>{% getBundle "css" %}</style>
3333
{#- Renders the CSS bundle using a separate file, if you can't set CSP directive style-src: 'unsafe-inline' #}
3434
{#- <link rel="stylesheet" href="{% getBundleFileUrl "css" %}"> #}
35+
36+
{#- Add the heading-anchors web component to the JavaScript bundle #}
37+
{%- js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
3538
</head>
3639
<body>
3740
<a href="#skip" class="visually-hidden">Skip to main content</a>
@@ -51,11 +54,16 @@
5154
</header>
5255

5356
<main id="skip">
54-
{{ content | safe }}
57+
<heading-anchors>
58+
{{ content | safe }}
59+
</heading-anchors>
5560
</main>
5661

57-
<footer></footer>
62+
<footer>
63+
<p><em>Built with <a href="https://www.11ty.dev/">{{ eleventy.generator }}</a></em></p>
64+
</footer>
5865

5966
<!-- This page `{{ page.url | htmlBaseUrl }}` was built on {% currentBuildDate %} -->
67+
<script type="module" src="{% getBundleFileUrl "js" %}"></script>
6068
</body>
6169
</html>

_includes/layouts/home.njk

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
layout: layouts/base.njk
33
---
4-
<!-- Delete this message, it will also remove the component CSS from the bundle -->
4+
<!-- Delete this block, which will also remove the component CSS from the bundle -->
55
{%- css %}{% include "public/css/message-box.css" %}{% endcss %}
66
<div class="message-box">
77
<ol>
8-
<li>Edit the <code>_data/metadata.js</code> with your blog’s information.</li>
8+
<li>Edit <code>_data/metadata.js</code> with your blog’s information.</li>
99
<li>(Optional) Edit <code>eleventy.config.js</code> with your <a href="https://www.11ty.dev/docs/config/">configuration preferences</a>.</li>
1010
<li>Delete this message from <code>_includes/layouts/home.njk</code>.</li>
1111
</ol>

_includes/layouts/post.njk

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: layouts/base.njk
33
---
4-
{# Only include the syntax highlighter CSS on blog posts #}
4+
{# Only include the syntax highlighter CSS on blog posts, included with the CSS per-page bundle #}
55
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
66
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
77
<h1>{{ title }}</h1>
@@ -21,8 +21,8 @@ layout: layouts/base.njk
2121
{%- set nextPost = collections.posts | getNextCollectionItem %}
2222
{%- if nextPost or previousPost %}
2323
<ul class="links-nextprev">
24-
{%- if previousPost %}<li>Previous: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
25-
{%- if nextPost %}<li>Next: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
24+
{%- if previousPost %}<li class="links-nextprev-prev">← Previous<br> <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
25+
{%- if nextPost %}<li class="links-nextprev-next">Next →<br><a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
2626
</ul>
2727
{%- endif %}
2828
{%- endif %}

content/404.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
---
2-
layout: layouts/home.njk
32
permalink: 404.html
43
eleventyExcludeFromCollections: true
54
---
65
# Content not found.
76

8-
Go <a href="/">home</a>.
7+
Go <a href="index.njk">home</a>.
98

109
<!--
1110

content/about.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---js
2+
const eleventyNavigation = {
3+
key: "About",
4+
order: 3
5+
};
6+
---
7+
# About
8+
9+
I am a person that writes stuff.

content/about/index.md

-9
This file was deleted.

content/blog.njk

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
---
2-
layout: layouts/home.njk
3-
eleventyNavigation:
4-
key: Archive
5-
order: 2
1+
---js
2+
const eleventyNavigation = {
3+
key: "Archive",
4+
order: 2
5+
};
66
---
77
<h1>Archive</h1>
88

content/blog/blog.11tydata.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = {
1+
export default {
22
tags: [
33
"posts"
44
],

content/blog/fifthpost.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
---
2-
title: This is a fifth post (draft)
3-
date: 2023-01-23
4-
draft: true
1+
---js
2+
const title = "This is a fifth post (draft)";
3+
const date = "2023-01-23";
4+
const draft = true;
55
---
66
This is a draft post

content/blog/firstpost.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
title: This is my first post.
33
description: This is a post on My Blog about agile frameworks.
44
date: 2018-05-01
5-
tags:
6-
- another tag
5+
tags: another tag
76
---
87
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
98

content/blog/fourthpost/fourthpost.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: This is my fourth post!
2+
title: This is my fourth post
33
description: This is a post on My Blog about touchpoints and circling wagons.
44
date: 2018-09-30
55
tags: second tag
@@ -8,7 +8,7 @@ Leverage agile frameworks to provide a robust synopsis for high level overviews.
88

99
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
1010

11-
{% image "./possum.png", "A possum parent and two possum kids hanging from the iconic red balloon" %}
11+
<img src="./possum.png" alt="A possum parent and two possum kids hanging from the iconic red balloon">
1212

1313
## Section Header
1414

content/blog/secondpost.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
title: This is my second post with a much longer title.
33
description: This is a post on My Blog about leveraging agile frameworks.
44
date: 2018-07-04
5-
tags:
6-
- number 2
5+
tags: number 2
76
---
87
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
98

109
## Section Header
1110

12-
<a href="/blog/firstpost/">First post</a>
13-
<a href="/blog/thirdpost/">Third post</a>
11+
<a href="/blog/firstpost.md">First post</a>
12+
<a href="blog/thirdpost.md">Third post</a>
1413

1514
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
1615

content/blog/thirdpost.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
title: This is my third post.
33
description: This is a post on My Blog about win-win survival strategies.
44
date: 2018-08-24
5-
tags:
6-
- second tag
7-
- posts with two tags
5+
tags: ["second tag", "posts with two tags"]
86
---
97
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
108

119
## Code
1210

13-
### Styled (with Syntax)
11+
### This is a very long heading that I want to wrap This is a very long heading that I want to wrap This is a very long heading that I want to wrap This is a very long heading that I want to wrap
1412

1513
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
1614

@@ -25,7 +23,7 @@ function myCommand() {
2523
console.log('Test');
2624
```
2725

28-
### Unstyled
26+
### Heading with a [link](#code)
2927

3028
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
3129

content/content.11tydata.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
layout: "layouts/home.njk",
3+
};

content/feed/.virtual

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
For RSS feed, Atom Feed, and JSON feed templates, see the plugin in eleventy.config.js

content/feed/feed.11tydata.js

-3
This file was deleted.

0 commit comments

Comments
 (0)