Deleted template content

This commit is contained in:
Ben Aultowski 2025-12-28 15:44:45 -05:00
parent eb53317ca2
commit 34330f23e0
84 changed files with 12 additions and 1793 deletions

View file

@ -1,11 +1,3 @@
email: hola@somemail.com
address: |-
Organization name
Your street
12345, city
Tel: +34 928231911
email: ben@aultowski@proton.me
platforms:
github: 'https://github.com/madrilene/eleventy-excellent'
mastodon: 'https://front-end.social/@lene'
bluesky: 'https://bsky.app/profile/lenesaile.com'
kofi: 'https://ko-fi.com/lenesaile'
bluesky: 'https://bsky.app/profile/hypnagaga.com'

View file

@ -48,14 +48,5 @@
{% include 'partials/theme-switch.njk' %}
<aside class="creator | cluster gutter-2xs text-step-min-1 mt-xl">
Made with <span class="visually-hidden">love</span> <span>{% svg "misc/heart" %}</span> and
<a class="no-indicator" href="https://www.11ty.dev/">
<span class="visually-hidden">Eleventy</span>
{% svg "misc/11ty" %}
</a>
by
<a href="{{ meta.creator.website }}">{{ meta.creator.name }}</a>
</aside>
</div>
</footer>

View file

@ -18,7 +18,7 @@ layout: base
<div class="wrapper flow prose">
<nav aria-label="Album navigation" class="cluster" style="--cluster-horizontal-alignment: space-between; --gutter: var(--space-s)">
<div>
<a href="{{ albumUrl }}" class="button" aria-label="Back to album">Contents</a>
<a href="{{ albumUrl }}" class="button" aria-label="Back to album track list">Track List</a>
</div>
<div class="cluster" style="--gutter: var(--space-xs)">
{% if prev %}
@ -38,7 +38,7 @@ layout: base
<nav aria-label="Album navigation" class="cluster" style="--cluster-horizontal-alignment: space-between; --gutter: var(--space-s)">
<div>
<a href="{{ albumUrl }}" class="button" aria-label="Back to album">Contents</a>
<a href="{{ albumUrl }}" class="button" aria-label="Back to album track list">Track List</a>
</div>
<div class="cluster" style="--gutter: var(--space-xs)">
{% if prev %}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View file

@ -1,90 +0,0 @@
---
title: Card
---
<p>
Previous to version 3, the card component was a Nunjucks include. There are a number of things that had to
be set before being able to use it, like the level of the heading or whether tags shall be displayed.
<a href="https://www.11ty.dev/docs/languages/webc/">WebC</a>
makes this easier, as you can now use the custom element and opt in to the different slots.
</p>
<h3>Available slots:</h3>
<ul>
<li>
<code>image</code>: has <code>slot="image"</code> on the
container (<code>picture</code> or <code>figure</code>) by default)
</li>
<li><code>headline</code>: display the card's main title</li>
<li>
<code>date</code> and <code>tag</code>: Grouped within the classes <code>meta</code> and <code>cluster</code> for date and tagging
information
</li>
<li><code>content</code></li>
<li><code>footer</code>: for links or whatever footer information</li>
</ul>
<p>I added some <strong>variants</strong>, avaliable via attribute selectors:</p>
<ul>
<li><code>img-square</code>: Enforces a square aspect ratio for images</li>
<li><code>clickable</code>: Makes the whole card clickable</li>
<li><code>no-padding</code>: Removes padding and background modifications</li>
</ul>
<h3>Usage</h3>
<pre><code>{% raw %}<!--prettier-ignore-->&lt;custom-card&gt;
{% image "path-to-img", "alt-text" %}
&lt;span slot="date"&gt;&lt;/span&gt;
&lt;span slot="tag" class="button"&gt;&lt;/span&gt;
&lt;h2 slot="headline"&gt;&lt;/h2&gt;
&lt;p slot="content"&gt;&lt;/p&gt;
&lt;footer slot="footer"&gt;&lt;/footer&gt;
&lt;/custom-card&gt;
{% endraw %}</code></pre>
<h3>Example</h3>
<div class="grid" data-layout="50-50">
<custom-card>
{% image "./src/assets/images/gallery/asturias-3.jpg", "Close-up of a delicate white flower with a yellow center, surrounded by green leaves" %}
<span slot="date">1516</span>
<span slot="tag" class="button" data-small-button>Default</span>
<h4 slot="headline">Utopia</h4>
<p slot="content">
Among them, there is no sort of traffic, no knowledge of letters, no understanding of numbers, no name
of magistrates, nor of politics, only of virtues; and they measure all things by barleycorns; their
money, plate, and other ornaments they so diligently polish that no rust can stick to them.
</p>
<footer slot="footer"><a href="#">Link in the footer</a></footer>
</custom-card>
<custom-card clickable img-square>
{% image "./src/assets/images/gallery/asturias-3.jpg", "Close-up of a delicate white flower with a yellow center, surrounded by green leaves" %}
<span slot="date">18.02.1984</span>
<div slot="tag" webc:nokeep>
<span class="button" data-small-button>clickable</span
><span class="button" data-small-button>square image</span>
</div>
<footer slot="footer"><a href="#">Link in the footer makes whole card a link</a></footer>
<h4 slot="headline">The order does not matter</h4>
</custom-card>
<custom-card>
<p slot="content">
They have no lawyers among them, for they consider them as a sort of people whose profession it is to
disguise matters and to wrest the laws [...].
</p>
<h4 slot="headline">Just title and content</h4>
</custom-card>
<custom-card no-padding>
{% image "./src/assets/images/gallery/asturias-3.jpg", "Close-up of a delicate white flower with a yellow center, surrounded by green leaves" %}
<p slot="content">
Red Hat's first logo appeared on an early invoice. It was a simple, bright red brimmed top hat placed
above the words "Red Hat Software."
</p>
<h4 slot="headline">This card has no padding</h4>
</custom-card>
</div>

View file

@ -1,56 +0,0 @@
---
title: Config
---
I like to divide things into small thematic areas, it helps me orient myself better. Configurations are structured into separate modules in `src/_config` and are then imported into the main configuration file.
- **collections.js**: Manages Eleventy collections such as posts and tags: https://www.11ty.dev/docs/collections/
- **events.js**: For code that should run at certain times during the compiling process: https://www.11ty.dev/docs/events/
- **filters.js**: Used within templating syntax to transform data into a more presentable format: https://www.11ty.dev/docs/filters/
- **plugins.js**: Everything I or Eleventy considers to be a plugin: https://www.11ty.dev/docs/plugins/
- **shortcodes.js**: Defines shortcodes for reusable content: https://www.11ty.dev/docs/shortcodes/
Each configuration category (filters, plugins, shortcodes, etc.) is modularized. or example, `dates.js` within the `filters` folder contains date-related filters.
```js
import dayjs from 'dayjs';
export const toISOString = dateString => dayjs(dateString).toISOString();
export const formatDate = (date, format) => dayjs(date).format(format);
```
These individual modules are then imported and consolidated in a central `filters.js` file, which exports all the filters as a single default object.
```js
import {toISOString, formatDate} from './filters/dates.js';
// more imports
export default {
toISOString,
formatDate,
// more exports
};
```
### Integration in Eleventy Config
In the main Eleventy configuration file (`eleventy.config.js`), these modules are imported:
```js
import filters from './src/_config/filters.js';
import shortcodes from './src/_config/shortcodes.js';
```
They are then used to register filters and shortcodes with Eleventy, using this nice concise syntax:
```js
eleventyConfig.addFilter('toIsoString', filters.toISOString);
eleventyConfig.addFilter('formatDate', filters.formatDate);
// More filters...
eleventyConfig.addShortcode('svg', shortcodes.svgShortcode);
```
This method hopefully keeps the Eleventy config clean and focused, only concerning itself with the registration of functionalities, while the logic and definition remain abstracted in their respective modules.
Some time ago I wrote a blog post about [how to organize the Eleventy configuration file](https://www.lenesaile.com/en/blog/organizing-the-eleventy-config-file/) where I go a little bit deeper into this topic.

View file

@ -1,55 +0,0 @@
---
title: CSS
---
Add and delete your globally available custom block stylesheets in `src/assets/css/global/blocks/*.css`.
The methodology used is [CUBE CSS.](https://cube.fyi/)
The CSS system of this starter was invented by Andy Bell. If you want to know exactly how it all works, and have a look at the (further elaborated) original, [read this article on piccalil.li](https://piccalil.li/blog/a-css-project-boilerplate/).
### Inline CSS and bundles
The main CSS file is now inline in production to improve performance, see `.src/_includes/head/css-inline.njk`.
You can add per-page or component bundles of CSS. Instead of adding your CSS file to the `src/assets/css/global/blocks/` directory, you can place them in `src/assets/css/local/`. All CSS files in there will be stored alongside `global.css` in `.src/_includes/css/`. You can now include them in the "local" bundle only on pages or components where you need them:
{% raw %}
```jinja2
{% css "local" %}
{% include "css/your-stylesheet.css" %}
{% endcss %}
```
{% endraw %}
### Component CSS
All CSS files placed in `src/assets/css/components/` will be sent to the output folder, where components can reference them: `/assets/css/components/*.css`.
### Debugging CSS
In `src/assets/css/global.css` you can decomment `@import-glob 'tests/*.css';` to include CSS for debugging.
It makes visible when your code[ wrapped in `<is-land>` elements](https://github.com/11ty/is-land) is being hydrated, where things might overflow and many other warnings and errors [that Heydon Pickering came up with](https://heydonworks.com/article/testing-html-with-modern-css/).
### Cascade layers
We now use cascade layers! Up until now, I used the `:where()` pseudo-class to create low specificity selectors for the reset and compositions. [Mayank inspired me](https://mayank.co/blog/css-reset-layer/) to change to cascade layers. We have two major bundles of CSS: everything included in "global" In `src/assets/css/global/global.css` is now organized in cascade layers. The "local" bundle is for per-page or component CSS, and does not use cascade layers - it has thus a higher specificity, independent of any selector specificity in the global CSS.
### Tailwind CSS
You will find that Tailwind CSS does not work as you might expect here. I explain this in [one of the blog posts](/blog/what-is-tailwind-css-doing-here/).
If you are working with **VS Code** I recommend installing the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) addon, as it works also for the custom utility classes.
If the IntelliSense does not seem to work in Nunjucks files, try adding this to your VS Code settings:
```json
"tailwindCSS.includeLanguages": {
"jinja-html": "html",
"jinja": "html",
"njk": "html"
},
```

View file

@ -1,29 +0,0 @@
---
title: Design tokens
---
Edit all your preferences (colors, fluid text sizes etc.) in `src/_data/designTokens/*.json`.
Additional colors, variants and gradients for custom properties are automatically created in `src/assets/css/global/base/variables.css` based on the colors set in `colors.json`.
In the [style guide](/styleguide/) you can see how everything turns out.
### Special case: colors
As of version 4.0, you can create colors dynamically. Run `npm run colors` after setting your color values in `src/_data/designTokens/colorsBase.json`. This will create / overwrite the required `colors.json` file in the same directory. These colors become custom properties (e.g. `--color-gray-100`) and utility classes similar to the Tailwind CSS syntax (for example `bg-gray-100`, `text-gray-900`).
If you want to adjust how the colors turn out, edit `src/_config/setup/create-colors.js`.
Colors placed under `shades_neutral` or `shades_vibrant` are converted into scalable palettes. `shades_neutral` is better for grayish / monochromatic colors, while `shades_vibrant` is better for colorful palettes. Colors listed under `standalone` and `light_dark` are left as they are, `light_dark` items output a second "subdued" version optimized for dark themes.
```js
// this creates a palette with shades of green, 100 to 900
"shades_vibrant": [
{
"name": "green",
"value": "#008000"
}
],
```
<strong class="text-pink">Important:</strong> If you change the color names, you must edit `src/assets/css/global/base/variables.css` with your color names. The rest of the CSS files should only reference custom properties set in `variables.css`.

View file

@ -1,26 +0,0 @@
---
title: Details
---
The `<custom-details>` WebC component has a corresponding Nunjucks include.
It uses the `<details>` and `<summary>` elements to create a collapsible section and enhances them aesthetically and functionally.
The JavaScript for the `<custom-details>` component adds functionality to buttons to expand and collapse the sections with one action. When JavaScript is disabled, the sections are still accessible and collapsible, but the extra buttons are hidden.
On page load, it checks if a hash corresponding to a details ID exists in the URL. If such an ID is found, the corresponding details section is programmatically opened, allowing direct navigation to an open section from a shared URL.
The sorting is set by default on "alphabetic", but you can also pass in "shuffle" or "reverse" as a parameter (directly in the `details.njk` partial).
### Usage
{% raw %}
```jinja2
{% set itemList = collections.docs %}
{% set headingLevel = "h2" %} {# optional, defaults to false #}
{% include 'partials/details.njk' %}
```
{% endraw %}
### Example
You are in the middle of a custom details component!

View file

@ -1,4 +0,0 @@
{
"tags": "docs",
"permalink": false
}

View file

@ -1,22 +0,0 @@
---
title: Easteregg
---
The `<custom-easteregg>` component is by default in the base layout in `src/_layouts/base.njk`. Just delete the two lines if you don't want to use it. The component is
designed to trigger a confetti effect when a user types a specific keyword sequence. It uses the dynamic import of the `canvas-confetti` library to render custom-shaped particles based on user input.
### Defaults:
- Keywords: `"eleventy"`, `"excellent"`
- Shape: `"⭐️"`
- Particle Count: `30`
### Customizable Attributes:
- `keyword`: custom keyword
- `shape`: custom shape for the confetti particles using emojis or text
- `particle-count`: number of particles to release during the effect
```js
<script type="module" src="/assets/scripts/components/custom-easteregg.js"></script>
<custom-easteregg keyword="yay" shape="🌈" particle-count="50"></custom-easteregg>
```

View file

@ -1,21 +0,0 @@
---
title: Favicons
---
All "necessary" favicons are in `src/assets/images/favicon`, and copied over to the root of the output folder.
I chose the sizes based on the recommendations from the [How to Favicon article on evilmartians.com.](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs)
You can place them in that directory manually, or use the script to automate the process:
```bash
npm run favicons
```
In this case define the SVG icon on which all formats are based on in `meta.js`:
```js
export const pathToSvgLogo = 'src/assets/svg/misc/logo.svg'; // used for favicon generation
```
Regardless of whether you generate the icons automatically or create them manually, it is best to keep the names so as not to break any reference to them. You can also use raster images instead of SVG.

View file

@ -1,13 +0,0 @@
---
title: Fonts
---
This starter uses two custom fonts, Red Hat Display and Atkinson Hyperlegible. You can add or delete fonts in `src/assets/fonts`.
I often create font subsets using the [Fontsquirrel Webfont Generator](https://www.fontsquirrel.com/tools/webfont-generator).
Next, edit `src/assets/css/global/base/fonts.css`.
Add your new font aliases in `src/_data/designTokens/fonts.json`.
Finally, in `src/_includes/head/preloads.njk` edit the font preloads.

View file

@ -1,39 +0,0 @@
---
title: Images
---
Using the [Eleventy Image](https://www.11ty.dev/docs/plugins/image/) plugin, there are three ways to handle image optimization: HTML Transform, Markdown syntax, and Nunjucks shortcodes. [See the dedicated blog post to dive (much) deeper.](/blog/post-with-an-image/)
Have a look at the [Attribute Overrides](https://www.11ty.dev/docs/plugins/image/#attribute-overrides) for the HTML Transform methods (1 and 2) for per instance overrides. Adding `eleventy:ignore` to an `<img>` element for example, skips this image.
### 1. HTML Transform
The HTML Transform automatically processes `<img>` and `<picture>` elements in your HTML files as a post-processing step during the build.
```html
<img src="./path/to/image.jpg" alt="alt text">
```
### 2. Markdown Syntax
The Markdown syntax creates the `<img>` element that the _HTML Transform plugin_ is looking for, and then transforms it to the `<picture>` element (if more than one format is set).
```markdown
![alt text](/path/to/image.jpg)
```
### 3. Nunjucks Shortcodes
In Nunjucks templates you can also use shortcodes (`image` and `imageKeys`).
{% raw %}
```jinja2
{% image '/path/to/image.jpg', 'alt text' %}
{% imageKeys {
"alt": "alt text",
"src": "/path/to/image.jpg"
} %}
```
{% endraw %}

View file

@ -1,36 +0,0 @@
---
title: JavaScript
---
This starter has **no real JS dependency**. If JavaScript is not available, components that rely on it -- like the theme switcher -- will be hidden. If you opted in for the drawer menu, pills will be shown instead.
There are two kinds of bundles for JavaScript in this starter, see `.src/_includes/head/js-inline.njk` and `.src/_includes/head/js-defer.njk`.
By default, I include Eleventy's [is-land](https://github.com/11ty/is-land) framework and the theme toggle inline.
You can include more scripts like so:
{% raw %}
```jinja2
{% js "inline" %}
{% include "scripts/your-inline-script.js" %}
{% endjs %}
```
{% endraw %}
Same goes for scripts that should be defered:
{% raw %}
```jinja2
{% js "defer" %}
{% include "scripts/your-defered-script.js" %}
{% endjs %}
```
{% endraw %}
Scripts stored in `src/assets/scripts/components/` are sent to the output folder, while scripts in `src/assets/scripts/bundle/` are sent to `.src/_includes/scripts/`, from where you can include them in the respective bundle.
Some components are enhanced with JavaScript.

View file

@ -1,39 +0,0 @@
---
title: Masonry
---
Masonry layout is not yet a native part of CSS grid. There is a debate if using `grid-template-rows: masonry;` is actually the best way to implement it.
It should be used carefully so we don't create confusion with the tabbing order. In version 3 of the starter I made the masonry layout a web component, and no longer a opt-in feature (was: `masonry: true` in the front matter).
`<custom-masonry>` is designed to function as a masonry grid by dynamically adjusting item positions based on the available column space and the size of its content. The necessary JavaScript (`custom-masonry.js`) is loaded only once per component usage due to the `data-island="once"` attribute.
Optional: pass in `layout="50-50"` to set a 50% width for each column.
If no JavaScript is available, the grid will fall back to the regular grid layout defined in `src/assets/css/global/compositions/grid.css`.
```js
<custom-masonry> (children) </custom-masonry>
<custom-masonry layout="50-50"> (children) </custom-masonry>
```
<div><custom-masonry>
<div style="background-color: var(--color-primary); aspect-ratio: 3/2;"></div>
<div></div>
<div style="background-color: var(--color-tertiary); aspect-ratio: 4/5;"></div>
<div style="background-color: var(--color-primary);"></div>
<div></div>
<div style="background-color: var(--color-secondary); aspect-ratio: 5/4;"></div>
<div></div>
<div style="background-color: var(--color-secondary);"></div>
<div style="background-color: var(--color-primary); aspect-ratio: 16/9;"></div>
<div></div>
</custom-masonry></div>
<style>
custom-masonry div {
inline-size: min(30rem, 100%);
aspect-ratio: 1;
background-color: var(--color-text);
}
</style>

View file

@ -1,57 +0,0 @@
---
title: Navigation
---
Edit your navigation items in `src/_data/navigation.js`.
You have two options for mobile navigation: by default, the navigation on small displays is converted to small pills that wrap. This does not require any additional JavaScript.
### Drawer Menu
You can activate a drawer menu for mobile in `src/_data/meta.js`:
```js
navigation: {
// other settings
drawerNav: true,
},
```
`drawerNav` activates the navigation drawer, [built according to Manuel Matuzović's article on web.dev.](https://web.dev/articles/website-navigation)
Adjust your menu breakpoint in `src/_data/designTokens/viewports.json`
```json
{
// ...
"navigation": 662,
// ...
}
```
### Submenu
You can activate submenus in `src/_data/meta.js`:
```js
navigation: {
// other settings
subMenu: true,
},
```
This includes the JavaScript for the submenu functionality. Add your submenu items to `src/_data/navigation.js` using this structure:
```js
{
text: 'Unlinked parent',
url: '#',
submenu: [
{
text: 'Sub Item',
url: '/sub-item/'
},
... more items
]
},
```

View file

@ -1,66 +0,0 @@
---
title: Open Graph images
---
You can see a [preview of the OG images in a blog post](/blog/open-graph-images/).
They are referenced in `meta-info.njk`:
{% raw %}
```html
<meta
property="og:image"
content="{{ meta.url }}
{% if (layout == 'post') %}/assets/og-images/{{ title | slugify }}-preview.jpeg
{% else %}{{ meta.opengraph_default }}
{% endif %}"
/>
```
{% endraw %}
To change the look and behaviour of those images and replace the SVG background edit `src/common/og-images.njk`.
The implementation is based on [Bernard Nijenhuis article.](https://bnijenhuis.nl/notes/automatically-generate-open-graph-images-in-eleventy/)
If you want to be inspired, have a look at [what Lea is doing here.](https://lea.codes/posts/2023-04-25-pseudorandom-numbers-in-eleventy/)
Consider that the domain is a hard coded value in the front matter.
**Important:** I have relocated the creation of the images in the development process, so that the font only needs to be installed on your own system. The images are located in `src/assets/og-images` and are comitted.
This is fine as long as you only work locally with Markdown, and the font is always installed on your system. If you work with a CMS you must add the font cto where the site is built. Some CMS let you add fonts into the `prebuild` config. Otherwise it usually falls down to the _Ubuntu_ Font Family. You still have to adjust the script `src/_config/events/svg-to-jpeg.js` to something like:
```js
import fs from 'fs';
import Image from '@11ty/eleventy-img';
export const svgToJpeg = async function () {
const ogImagesDir = 'dist/assets/og-images/';
fs.readdir(ogImagesDir, (err, files) => {
if (!!files && files.length > 0) {
files.forEach(fileName => {
if (fileName.endsWith('.svg')) {
let imageUrl = ogImagesDir + fileName;
Image(imageUrl, {
formats: ['jpeg'],
outputDir: './' + ogImagesDir,
filenameFormat: function (id, src, width, format, options) {
let outputFileName = fileName.substring(0, fileName.length - 4);
return `${outputFileName}.${format}`;
}
});
}
});
} else {
console.log('⚠ No social images found');
}
});
};
```
### Regenerating OG images
As you make changes, possibly adjust the title of your post or delete it, the images add up in `src/assets/og-images`. To delete this folder and regenerate all images, you can run `npm run clean:og`.
Let me know if you encounter any problems.

View file

@ -1,51 +0,0 @@
---
title: Pagination
---
The blog posts use [Eleventy's pagination feature](https://www.11ty.dev/docs/pagination/). The logic for this can be found in tha partial `src/_includes/partials/pagination.njk`, the layout `src/_layouts/blog.njk` includes it, how many entries should be on a page is defined in `src/pages/blog.md`.
If you do not want any pagination at all, it is easiest to set a very high number for the pagination size, for example:
```yaml
pagination:
data: collections.posts
size: 10000
```
In `src/_data_/meta.js` you can set some values for the visible content (previous / next buttons) and the aria labels.
You can also **hide the number fields** between the previous and next buttons by setting `paginationNumbers` to `false`.
```js
blog: {
// other adjustments
paginationLabel: 'Blog',
paginationPage: 'Page',
paginationPrevious: 'Previous',
paginationNext: 'Next',
paginationNumbers: true
}
```
If you want to change the collection that is paginated (by default `collections.posts`), you must do so in two places: the front matter of the template, `src/pages/blog.md`:
```yaml
pagination:
data: collections.posts
```
and where the pagination component is included: `src/_layouts/blog.njk`:
{% raw %}
```jinja2
<!-- set collection to paginate -->
{% set collectionToPaginate = collections.posts %}
<!-- if the number of items in the collection is greater than the number of items shown on one page -->
{% if collectionToPaginate.length > pagination.size %}
<!-- include pagination -->
{% include 'partials/pagination.njk' %}
{% endif %}
```
{% endraw %}

View file

@ -1,9 +0,0 @@
---
title: Platforms (icons)
---
Find and set your platform icons in `src/assets/svg`, in the "platform" directory.
In `src/_data/personal.yaml` you can edit the platforms. The key should be the same as the name of the icon. For example: `mastodon: 'https://front-end.social/@lene'` and `src/assets/svg/platform/mastodon.svg`.
https://simpleicons.org/ features a great variety of free SVG icons for popular platforms.

View file

@ -1,56 +0,0 @@
---
title: Schema
---
Schema markup provides additional context for search engines and screen readers. The main schema template is included in the `<head>` via `src/_includes/head/schema.njk`. New schemas should be placed in `src/_includes/schemas/`.
To use the "BlogPosting" schema, set the schema key in the front matter:
```yaml
---
schema: BlogPosting
---
```
To use an Event schema for example, create a template at `src/_includes/schemas/Event.njk`, with something similar to:
{% raw %}
```jinja2
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Event",
"location": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "{{ event.data.place.city }}",
"postalCode": "{{ event.data.place.plz }}",
"streetAddress": "{{ event.data.place.street }}"
},
"name": "{{ event.data.place.name }}"
},
"name": "{{ event.data.title }}",
"description": "{{ event.data.description }}",
"startDate": "{{ event.data.date }}",
"performer": "{{ event.data.artist }}"
}
</script>
```
{% endraw %}
And reference it in the front matter:
```yaml
---
schema: Event
---
```

View file

@ -1,24 +0,0 @@
---
title: SVG
---
All SVG icons used in the starter are in `src/assets/svg`. There is a directory dedicated to the dividers, the platform icons and a general folder called "misc".
### Shortcode
The `svg.js` shortcode, introduced in version 3, allows for the seamless inclusion of SVG files. Located in `src/_config/shortcodes/svg.js`, this shortcode requires only the folder and file name of the SVG, omitting the file extension. By default, SVGs are injected with an `aria-hidden="true"` attribute. The SVGs should be stored in the `src/assets/svg` directory, and referenced using the format `"folder/svg-name"`.
{% raw %}
```jinja2
{% svg "path", "aria-name", "class-name", "inline-style" %}
{% svg "misc/star", "A yellow star icon", "spin", "block-size: 4ex; fill: var(--color-tertiary);" %}
```
{% endraw %}
{% svg "misc/star", "A yellow star icon", "spin", "block-size: 4ex; fill: var(--color-tertiary);" %}
The star icon resoves to:
`<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 24 24" aria-label="A yellow star icon" style="block-size: 4ex; fill: var(--color-tertiary)" class="spin"><path> (...) </path></svg>`

View file

@ -1,21 +0,0 @@
---
title: Tags
---
This was probably the most opinionated decision: tags have been integrated since version 2.0.
The tags are placed in the front matter of the posts, using the syntax
```yaml
tags:
- image
- feature
```
or
```md
tags: ['markdown', 'feature']
```
If you generally do not want any tags to show, it is probably easiest to not create any at all.

View file

@ -1,42 +0,0 @@
---
title: Template Languages
---
We use the following [template languages](https://www.11ty.dev/docs/languages/):
- [Nunjucks](https://www.11ty.dev/docs/languages/nunjucks/)
- [Markdown](https://www.11ty.dev/docs/languages/markdown/)
- [WebC](https://www.11ty.dev/docs/languages/webc/)
### Nunjucks
Nunjucks Docs: [https://mozilla.github.io/nunjucks/templating.html](https://mozilla.github.io/nunjucks/templating.html)
[prettier-plugin-jinja-template](https://github.com/HookyQR/prettier-plugin-jinja-template) is used for Nunjucks code formatting. It is configured in `.prettierrc`.
I use [Better Jinja](https://github.com/samuelcolvin/jinjahtml-vscode) for syntax highlighting. After installing it for your code editor, you can configure the file associations in your settings:
```
{
"files.associations": {
"*.njk": "jinja-html"
}
}
```
Nunjucks was inspired by Jinja2, which is a Python templating engine. The syntax is very similar. I did not find good syntax-highlighting and formatting solutions specifically made for Nunjucks, but everything Jinja2 works just fine.
### Markdown
Eleventy uses [markdown-it](https://github.com/markdown-it/markdown-it) for markdown files (.md). The custom configuration for this starter is in `src/_config/plugins/markdown.js`.
### WebC
[WebC](https://github.com/11ty/webc) is standalone HTML serializer for generating markup for Web Components. We use the [WebC plugin](https://github.com/11ty/eleventy-plugin-webc) for Eleventy.
We combine WebC components with Nunjucks partials:
```bash
src/_includes/webc/custom-card.webc # WebC component definition
src/_includes/partials/card-blog.njk # Nunjucks partial with logic
src/_includes/partials/card-tag.njk # Another partial using the same component
```

View file

@ -1,30 +0,0 @@
---
title: Tests
---
You can run local automated accessibility tests with [pa11y-ci](https://github.com/pa11y/pa11y-ci).
`src/common/pa11y.njk` generates a _pa11y-ci_ config file for all pages in the sitemap by default. You can also define custom paths to test in `src/_data/meta.js`, whithin `tests.pa11y.customPaths`.
To run the tests, use the following command:
```bash
npm run test:a11y
```
This command will:
1. Build the site in test environment
2. Start a preview server on `localhost:8080`
3. Run `pa11y-ci` accessibility tests against all pages in the sitemap, or the custom paths.
### Ignoring Rules
To ignore specific rules, you can add them to the front matter of a template:
```yaml
pa11yIgnore:
- "WCAG2AA.Principle1.Guideline1_4.1_4_3.G145.Fail"
- "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail"
```
or globally in `src/_data/meta.js`, within `tests.pa11y.globalIgnore`.

View file

@ -1,17 +0,0 @@
---
title: Theme (dark / light mode)
---
With version 2.0 I introduced dark and light mode. This is not intended to be a gimmick, but to support the accessibility of the site. And I tend to read blog posts at night, and if there is no dark mode then I leave the tab for later, and we all know how that ends.
Dark and light mode respects the user agent or operating system settings using the `prefers-color-scheme` CSS media feature. But there is also a switch in the `<footer>`.
If you want to change something here, for example replace the button with a sun/moon icon, make sure to preserve accessibility.
The accessible name ("Theme dark" or "Theme light") is put together by `aria-labelledby="theme-switcher-label"` resolving to "Theme" and the `<button>`s "light" and "dark".
If your site is in another language, you can adjust those values in `_data/meta.js`, for both the content of the `<button>`s and their `aria-label`.
If you remove the "light" and "dark" `<button>` and you don't use the heading with the ID `theme-switcher-label`, the value for the accessible name must be obtained differently.
If you find any accessibility issues, please let me know.

View file

@ -1,50 +0,0 @@
---
title: Video
---
### YouTube
`<custom-youtube>` is a wrapper around [Lite YouTube Embed](https://github.com/paulirish/lite-youtube-embed), optimizing video playback for performance.
`@slug` video ID
`@start` (optional) start time in seconds
`@label` Used for accessibility and the `<custom-youtube-link>` fallback
`@poster` (optional) custom poster image URL (with https://v1.opengraph.11ty.dev/)
`@posterSize` (optional, default: 'auto') size passed in to custom poster
`@jsapi` (optional, default: 'undefined') Enables [JavaScript API support](https://github.com/paulirish/lite-youtube-embed?tab=readme-ov-file#access-the-youtube-iframe-player-api).
```html
<custom-youtube
@slug="Ah6je_bBSH8"
@label="Alberto Ballesteros - Artista Sin Obra">
</custom-youtube>
```
<div><custom-youtube @slug="Ah6je_bBSH8" @label="Alberto Ballesteros - Artista Sin Obra"> </custom-youtube></div>
### PeerTube
`<custom-peertube>` is a wrapper around [PeerTube](https://joinpeertube.org/)s embed system.
`@instance` PeerTube domain hosting the video
`@embed-slug` The unique ID used in the embed URL.
`@start` (optional) start time
`@slug` unique video identifier for direct links in the `<custom-peertube-link>` fallback
`@label` Used for accessibility and the `<custom-peertube-link>` fallback.
```html
<custom-peertube
@instance="peertube.tv"
@slug="s2oueWPpbhhUrWM6tewHYf"
@embed-slug="d2bf34fc-6cee-455e-86dc-b7e8979fd1a2"
@label='Morgan the Organ on Tour'>
</custom-peertube>
```
<div>
<custom-peertube
@instance="peertube.tv"
@slug="s2oueWPpbhhUrWM6tewHYf"
@embed-slug="d2bf34fc-6cee-455e-86dc-b7e8979fd1a2"
@label='Morgan the Organ on Tour'>
</custom-peertube>
</div>

View file

@ -1,18 +0,0 @@
---
title: What can be deleted
---
**Everything, of course**
This is still meant to be a starter, even though it grew to be more like a template.
If you want to keep the defaults, but get rid of the example content, delete the following files and archives:
- `github.js` in `src/_data/`
- `builtwith.json` in `src/_data/`
- all files in `src/posts`
- the directory and all files in `src/docs`
- all pages in `src/pages`, though you might want to keep `index.njk` as a starting point
- You can delete `screenshots`, `blog` and `gallery` in `src/assets/images`.
Keep the `favicon` and `template` folders though.
If you don't want to feature any code examples, you may delete the whole stylesheet for syntax highlighting: `src/assets/css/global/blocks/code.css`.
In general, any CSS block in there is optional.

View file

@ -18,7 +18,7 @@ permalink: 'blog/{% if pagination.pageNumber >=1 %}page-{{ pagination.pageNumber
</header>
<div class="region flow prose" style="--region-space-top: var(--space-xl-2xl)">
<p>This blog has a pagination of <strong>{{ pagination.size }}</strong> posts per page.<br>
<p>This sectionas a pagination of <strong>{{ pagination.size }}</strong> posts per page.<br>
The pagination is only shown if there are more posts ({{ collections.posts.length }}) than items per
page ({{ pagination.size }}).
</p>

View file

@ -1,61 +0,0 @@
---
title: Built with
permalink: /built-with/index.html
description: 'A list of sites based on / built with Eleventy Excellent. Add yours by submitting a pull request!'
layout: page
sizes: '(max-width: 615px) 50vw, 100vw'
widths: [400, 520]
---
<p>
Honestly, I made this starter for myself, based on how I want to start a project and how I like to organize
everything. I am delighted that so many of you find it useful too! This is a list of sites based on / built
with Eleventy Excellent. This uses Eleventy's
<a href="https://www.11ty.dev/docs/services/screenshots/">screenshot API </a>. New screenshots are fetched
in development only.
</p>
<p>
Have you built a site with this starter? Please let me know or create a
<a
href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request"
rel="noopener"
>pull request</a
>
and add it to the list! Add your data in <code>src/_data/builtwith.json</code>, then run
<code>npm run screenshots</code> to add or update the screenshots.
</p>
<article class="full section" style="--spot-color: var(--color-bg-accent)">
{% svg "divider/soft-top", null, "divider" %}
<section class="feature section__inner wrapper">
<h2>Based on, or built with Eleventy Excellent:</h2>
<div
class="grid feature region"
style="--region-space-top: var(--space-xl); --gutter: var(--space-xl) var(--space-xs)"
>
<!-- you find tha data for that in src/_data/builtwith.json -->
{% for site in builtwith | shuffle %}
<custom-card clickable img-square class="text-step-min-1" style="--card-bg: var(--color-bg)">
{% image "./src/assets/images/screenshots/" + site.filename + ".jpg", site.name, null, "lazy", null, null, widths, sizes %}
<h3 slot="headline" class="text-step-min-1">{{ site.name }}</h3>
<p slot="content">{{ site.description }}</p>
<footer slot="footer" class="repel">
<a class="no-indicator" href="{{ site.link }}">{{ site.link | replace("https://", "") }}</a>
{% if site.builtbylene %}
<span class="gradient-text-linear">built by Lene</span>
{% endif %}
</footer>
</custom-card>
{% endfor %}
</div>
</section>
{% svg "divider/soft-bottom", null, "divider" %}
</article>
{% css "local" %}
{% include "css/custom-card.css" %}
{% endcss %}

View file

@ -1,25 +0,0 @@
---
title: Get started
permalink: /get-started/index.html
description: 'You can use this starter as a template for your blog and you are ready to go! But there are some adjustments you have to make.'
layout: page
---
You can use this starter as a template for your blog and you are ready to go! But there are some **adjustments you have to make**.
- `src/_data/meta.js` - sets different "hard coded" text values all over the template, you can change the language, etc.
- edit your personal details and social media in `src/_data/personal.yaml`.
- Open `src/assets/css/global/blocks/external-link.css`. Replace "eleventy-excellent.netlify.app" with your own domain. This is about the external link indicators, they are matched with your domain. If you don't want to use external link indicators, feel free to delete the whole style rule. You can also add the class `no-indicator` to any anchor element you want to except from this rule.
The [blog posts](/blog/) also explain / show some features that aren't covered here.
## "Docs" lol
<!-- loop docs -->
{% set itemList = collections.docs %}
{% set headingLevel = "h2" %}
{% include 'partials/details.njk' %}
{% css "local" %}
{% include "css/custom-card.css" %}
{% endcss %}

View file

@ -1,8 +1,8 @@
---
layout: base
permalink: /index.html
title: 'Eleventy Excellent'
description: 'Eleventy starter using modern CSS, fluid type, fluid spacing, flexible layout and progressive enhancement.'
title: 'Hypnagaga'
description: 'The front page of a web site, very much under construction.'
blog:
title: 'Blog'
intro: "I'm showing the last 4 blog posts, but there might be more!"
@ -13,24 +13,18 @@ blog:
<div class="section__inner flow region">
<h1 class="text-center" style="color: var(--color-light);">{{ title }}</h1>
</div>
{% svg "divider/waves", null, "divider" %}
{% svg "divider/spikes", null, "divider" %}
</header>
<article class="full | region">
<div class="prose wrapper flow">
<h2 id="an-eleventy-starter">An Eleventy starter</h2>
<h2 id="an-eleventy-starter">Surprise, its filler text!</h2>
<p>
Built around a CSS workflow that emphasizes guiding browser styling rather than micromanaging it. It
incorporates progressive enhancement, fluid type and spacing, and utilizes modern CSS features for
layout. The goal is to develop frontends that provide a great experience across all devices,
connection speeds, and usage contexts.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc malesuada enim turpis, vel rhoncus lectus pretium et. Ut porttitor, justo semper ultricies blandit, felis sapien congue leo, ac maximus magna felis id risus. Aenean consequat, leo sed feugiat consectetur, metus velit consectetur purus, sed feugiat ipsum nisi finibus eros. Fusce eu placerat ex, sit amet rutrum metus. Integer volutpat diam est, a tempus velit faucibus vel. Vestibulum ullamcorper, leo sed bibendum laoreet, mi orci maximus ante, nec malesuada enim arcu eu nisl. Nam scelerisque felis augue, non tempus enim tincidunt eget.
</p>
<p>
<strong>This is <a href="https://github.com/madrilene/eleventy-excellent/">version {{ pkg.version }}</a>.</strong> I keep a
<a href="https://github.com/madrilene/eleventy-excellent/tree/v1">branch of v1</a>,
<a href="https://github.com/madrilene/eleventy-excellent/tree/v2">v2</a> and <a href="https://github.com/madrilene/eleventy-excellent/tree/v3">v3</a>. I tried to <a href="/get-started/#docs-lol">document most features and methodologies</a>.
Morbi maximus, purus non faucibus condimentum, turpis nunc scelerisque arcu, at condimentum quam eros eget nibh. Curabitur eu nibh egestas, tempor ante sit amet, elementum sem.
</p>
<p><strong>Have fun</strong> and let me know if you find any issues or have ideas for improvements!</p>
</div>
</article>

View file

@ -1,26 +0,0 @@
---
title: 'Post with fetched content'
description: 'Eleventy Fetch fetches and caches resources - at configurable intervals. In this example I am fetching my public repositories with a cache duration of 1 day.'
date: 2022-08-28
tags: ['fetch', 'feature']
---
[Eleventy Fetch](https://www.11ty.dev/docs/plugins/fetch/) fetches and caches resources -- at configurable intervals.
This is an example of fetching external data.
In this case, my public repositories (with more than 20 stargazer) and a cache duration of 1 day.
Endpoint editable in `_data/github.js.`
{% for repository in github %}
{% if repository.stargazers_count > 20 %}
<h2>{{ repository.name }}</h2>
{{ repository.html_url }}
**{{ repository.stargazers_count }} GitHub stars**
{{ repository.description }}
{% endif %}
{% endfor %}

View file

@ -1,23 +0,0 @@
---
title: 'Post with 301 redirects'
description: 'A 301 is used when a page has permanently changed location. Informing about this change is indispensable if you want to keep a positioning. Aleksandr Hovhannisyan came up with an elegant solution for Eleventy and Netlify.'
date: 2022-08-28
tags: ['redirects', 'feature']
redirectFrom: ['/old-route/', '/optionally-another-old-route/']
---
URLs usually change over time, as you use another CMS or optimize your file structure.
A 301 is used when a page has permanently changed location.
Informing about this change is indispensable if you want to keep your incoming links working, be it from organic Google search or other pages that have linked to your content.
Aleksandr Hovhannisyan came up with an [elegant solution for Eleventy and Netlify](https://www.aleksandrhovhannisyan.com/blog/eleventy-netlify-redirects/). To directly cover several possible previous routes it is created as an array. You can find the loop in `_redirects.njk`.
## Usage
```yaml
Frontmatter:
---
redirectFrom: ['/old-route/', '/optionally-another-old-route/']
---
```

View file

@ -1,38 +0,0 @@
---
title: 'Post with some code'
description: 'Syntax Highlighting is achieved by a pack of Eleventy plugins. No browser/client JavaScript, highlight transformations are all done at build-time.'
date: 2022-09-01
tags: ['syntax highlighting', 'feature']
---
This theme uses 11ty's [Syntax Highlighting Plugin](https://www.11ty.dev/docs/plugins/syntaxhighlight/), a pack of Eleventy plugins for PrismJS syntax highlighting. No browser/client JavaScript, highlight transformations are all done at build-time.
```js
const cards = [...document.querySelectorAll('.card')];
cards.forEach(card => {
card.style.cursor = 'pointer';
let down,
up,
link = card.querySelector('a');
card.onmousedown = () => (down = +new Date());
card.onmouseup = () => {
up = +new Date();
if (up - down < 200) {
link.click();
}
};
});
// © Heydon Pickering
```
```css
.smol-container {
width: min(100% - 3rem, var(--container-max, 60ch));
margin-inline: auto;
}
/* © Stephanie Eckles, https://smolcss.dev/ */
```
Edit styles in `css/blocks/code.css`

View file

@ -1,26 +0,0 @@
---
title: 'Post with a video'
description: "This starter uses Paul Irish's lite-youtube-embed web component. You can also use a modified version to display PeerTube videos."
date: 2022-10-31
tags:
- youtube
- peertube
- feature
---
This starter uses a [webC version](https://github.com/zachleat/zachleat.com/blob/main/_components/youtube-lite-player.webc) of Paul Irish's [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed).
<div>
<custom-youtube @slug="Ah6je_bBSH8" @label="Alberto Ballesteros - Artista Sin Obra"></custom-youtube>
</div>
A modified version to display [PeerTube](https://joinpeertube.org/) videos is also included (Thank you [camperotactico](https://github.com/camperotactico)). It works similarly, but takes two extra arguments:
- `@instance`: The instance hosting the video.
- `@embed-slug` The slug used for video embedding.
<div>
<custom-peertube @instance="fair.tube" @slug="8opkviMc2iDUYMwJzG1FQ4" @embed-slug="3bd0b70e-7890-4216-a123-2052363645ff" @label='Back at the Herperduin 💦 - 28/09/2024'></custom-peertube>
</div>
[Learn more in the video docs. ](http://localhost:8082/get-started/#video)

View file

@ -1,143 +0,0 @@
---
title: 'Post with all the markdown'
description: 'A lot of markdown packages are installed to help you write your posts. All presets are personal preference.'
date: 2022-11-02
tags: ['markdown', 'feature']
---
A lot of markdown packages are installed to help you write your posts.
You can configure them in `config/plugins/markdown.js`.
As of my personal preference, there are some presets. For example the conversion of web pages to links (www.lenesaile.com) and the addition of `rel="noopener"` for external links (all links with the pattern `/^https?:/`).
**This is a tiny pitfall!**
Take care to not prefix your internal links with your domain, or else they will be treated as external. To link internally, use this pattern:
```markdown
An internal link to the [about page](/about/)
```
## h2 Heading
### h3 Heading
#### h4 Heading
Muffin bonbon jujubes cheesecake chupa chups shortbread ice cream cotton candy cake. Jelly-o biscuit dessert danish dessert pastry tootsie roll lemon drops gingerbread. Cheesecake donut marzipan sweet roll icing muffin halvah. Dragée donut cake biscuit pie carrot cake sesame snaps jelly-o gummi bears.
Soufflé topping shortbread lemon.
## hr
---
## Typographic replacements
**The replacement converts this input:**
```markdown
(c) (C) (r) (R) (tm) (TM) +-
and so on.. and so on... and so on..... AND SO ON???????.....
WTF!!!!!! How many exclamation marks are you going to use????????????
,, -- ---
"double quotes" and 'single quotes'
```
**To this:**
(c) (C) (r) (R) (tm) (TM) +-
and so on.. and so on... and so on..... AND SO ON???????.....
WTF!!!!!! How many exclamation marks are you going to use????????????
,, -- ---
"double quotes" and 'single quotes'
## Emphasis
**This is bold text**
_This is italic text_
~~Strikethrough~~
## Blockquote
> Cheesecake donut marzipan sweet roll icing muffin halvah. Dragée donut cake biscuit pie carrot cake sesame snaps jelly-o gummi bears. Cotton candy cookie croissant fruitcake.
## Lists
### Unordered lists
- Create a list by starting a line with `+`, `-`, or `*`
- Another item
### Ordered lists
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
## Code
Syntax highlighting
```css
.back-top-top {
padding: 10px;
background: white;
margin-top: 110vh;
position: sticky;
bottom: 0;
}
/* by David Darnes */
```
## Tables
| Technology | Fun fact |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| HTML | HTML (Hypertext Markup Language) was created by Sir Tim Berners-Lee in 1991 as a way to structure and link documents on the World Wide Web. |
| CSS | It's called "cascading" because styles can cascade down from parent elements to their children, allowing for inheritance and overriding. |
| JavaScript | TypeError: null is not an object |
## Links
[Read all those articles](https://moderncss.dev/)
Autoconverted link https://every-layout.dev/ (enabled via linkify)
## Emojis
**Literal:**
🤩 💯 💚 👻 👾
**Classic markup:**
:cry: :poop: :fire: :laughing: :christmas_tree:
([A reference for emoji markup](https://gist.github.com/rxaviers/7360908))
**Shortcuts (emoticons)**:
:-) :-( 8-) ;) :-P
## mark
==Marked text==
## Footnotes
Footnote 1 link[^first].
Footnote 2 link[^second].
[^first]:
Footnote **can have markup**
and multiple paragraphs.
[^second]: Footnote text.
\*[HTML]: Hyper Text Markup Language
## Images
Consider that `src` is already prepended in the settings.
![Close-up with unfocused background of a vibrant large blue butterfly gracefully perched on a delicate flower amidst lush green grass](/assets/images/gallery/asturias-4.jpg)
{%- css "local" -%}
{%- include 'css/table.css' -%}
{%- endcss -%}

View file

@ -1,20 +0,0 @@
---
title: 'Open Graph images'
description: 'When you share your blog posts, a thumbnail image might appear. This starter generates these images for your blog posts automatically.'
date: 2023-01-25
tags:
- image
- feature
---
When you share your blog posts, a thumbnail image may appear - the image we define in our meta data as an Open Graph Image (`og:image`).
This starter generates these images for your blog posts automatically. They take in the title and date of the post.
![Open Graph image preview of a blog Post. 'Eleventy Excellent 2.0' is written as a large title in the center, the date is shown above and the name and URL of the website is seen on the bottom. The background consists of layered pink color areas resembling a city skyline](/assets/images/blog/og-preview.jpeg 'This is what an OG image for a blog posts looks like')
The fallback and default image for all other pages is the image set as `opengraph_default` in the `meta.js` global data file.
{% image "./src/" + meta.opengraph_default, meta.opengraph_default_alt, "This is what the general OG image for non-blog posts looks like" %}
A more detailed explanation can be found in the [docs](/get-started/#open-graph-images).

View file

@ -1,35 +0,0 @@
---
title: 'Demo pages'
description: 'As of version 2.0, the demos featured here are all directly built in the starter.'
date: 2023-10-30
demos:
- title: Gallery
description: 'A gallery with good old "popup" functionality inside a dialog element and a regular loop over images.'
preview: '/blog/post-with-a-gallery/'
- title: Pagination
description: 'The blog collection with a pagination. To work with visual current page indication, :has() pseudo-class support is required.'
preview: '/blog/'
- title: Tags
description: 'The blog has a basic tag system. Tags can be stored in front matter, as a YAML list or as an array.'
preview: '/tags/'
---
**Important**: As of version 2.0, the demos featured here are all directly built in the starter.
I did not want to clutter the starter with too many features, that you might not need, but I find myself using them frequently for my own projects, so now they are "baked in".
I will keep the old demo repos for the moment, but they are not maintained and are deprecated.
If you never saw version 1, nevermind.
## Demos
{% for item in demos %}
<article class="flow my-m-l">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}
<div class="cluster">
<a class="button no-indicator" href="{{ item.preview }}">Demo</a>
</div>
</article>
{% endfor %}

View file

@ -1,80 +0,0 @@
---
title: 'What is Tailwind CSS doing here?'
description: 'We are using Tailwinds "engine" to generate utility classes on demand, based on our design tokens. '
date: 2023-11-30
---
**Update February 2024:**
The CSS system of this starter was invented by Andy Bell.
I wrote the following explanation quite quickly after hearing several times that people are confused about normal Tailwind CSS classes not working. In the meantime, Andy has published a [better and more detailed explanation](https://piccalil.li/blog/a-css-project-boilerplate/).
---
We are using Tailwinds "engine" to generate utility classes on demand, based on our design tokens.
If you have a look at the [tailwind.config.js](https://github.com/madrilene/eleventy-excellent/blob/main/tailwind.config.js), you can see how that is done. For example, we are [deactivating Tailwinds default reset](https://github.com/madrilene/eleventy-excellent/blob/main/tailwind.config.js#L72C1-L72C22).
We are hooking into the components layer, to make Tailwind output classes based on our tokens, instead of their default design system.
That is, you are able to use `mt-xs-s` instead of a class like `mt-20` for example. Same goes for colors, depending on the namesin your `colors.json`, you get custom classes like `text-pink`. These use the usual Tailwind prefixes ([see docs to learn how to generate colors](/get-started/#design-tokens)).
You get a custom property mapped to the color name `--color-my-custom-color-name` _and_ the classes `bg-my-custom-color-name` as well as `text-my-custom-color-name`.
Consider that we limit those utilities in the theme section:
```js
backgroundColor: ({theme}) => theme('colors'),
textColor: ({theme}) => theme('colors'),
margin: ({theme}) => ({ auto: 'auto', ...theme('spacing')}),
padding: ({theme}) => theme('spacing')
```
If you want to add the generation for `border-color` classes for example, you'd have to add that right there:
`borderColor: ({theme}) => theme('colors')`
Also. you _do_ have something like `md:text-right` available because we define the screens (`src/_data/designTokens/viewports.json`):
```js
screens: {
ltsm: {max: `${viewportTokens.sm}px`},
sm: `${viewportTokens.sm}px`,
md: `${viewportTokens.md}px`,
navigation: `${viewportTokens.navigation}px`
},
```
Additionally, you get custom properties based on the naming of your design token files:
```js
const groups = [
{key: 'colors', prefix: 'color'},
{key: 'borderRadius', prefix: 'border-radius'},
{key: 'spacing', prefix: 'space'},
{key: 'fontSize', prefix: 'size'},
{key: 'lineHeight', prefix: 'leading'},
{key: 'fontFamily', prefix: 'font'},
{key: 'fontWeight', prefix: 'font'}
];
```
In your dev tools you can see all the generated custom properties + your custom ones from `css/global/variables.css`.
They are generated by default.
![Screenshot of the Firefox dev tools, CSS tab, showing the generated custom properties](/assets/images/blog/custom-properties.png)
You can also create custom utility classes:
```js
const customUtilities = [
{key: 'spacing', prefix: 'flow-space', property: '--flow-space'},
{key: 'spacing', prefix: 'region-space', property: '--region-space'},
{key: 'spacing', prefix: 'gutter', property: '--gutter'}
];
```
If you install the Tailwind CSS IntelliSense addon, you can actually see the classes available to you, including the color preview.
![Screenshot in VS Code showing the available flow-space-classes we created, using the Tailwind CSS IntelliSense addon](/assets/images/blog/intellisense.png)
Read some thoughts that lead Andy Bell to come up with that approach: https://andy-bell.co.uk/i-used-tailwind-for-the-u-in-cube-css-and-i-liked-it/

View file

@ -1,32 +0,0 @@
---
title: 'Post with a gallery'
description: 'A gallery with good old "popup" functionality inside a dialog element, a new image shortcode that links directly to the image with its original dimensions, and a regular loop over images.'
date: 2024-01-30
gallery:
- image: ./src/assets/images/gallery/asturias-1.jpg
alt: 'A picturesque valley showcasing majestic mountains and lush forests, creating a serene and captivating landscape'
caption: 'Inside the Somiedo Natural Park, Asturias'
- image: ./src/assets/images/gallery/asturias-2.jpg
alt: 'Close-up of a delicate white flower with a yellow center, surrounded by green leaves'
caption: 'Jasmine nightshades blooming in July'
- image: ./src/assets/images/gallery/asturias-3.jpg
alt: "A traditional Asturian village with it's raised granaries, surrounded by lush green hills and mountains"
caption: 'Traditional houses in Santullano, Somiedo Natural Park, Asturias'
- image: ./src/assets/images/gallery/asturias-4.jpg
alt: 'Close-up with unfocused background of a vibrant large blue butterfly gracefully perched on a delicate flower amidst lush green grass'
caption: 'A large blue (Phengaris arion)'
---
This post has a gallery set in its front matter as a list of objects, each with an `image`, `alt`, and `caption` property.
When you import the gallery component, the images are listed in a grid as buttons, each linked to the respective image in a `<dialog>` HTML element. A close button within each dialog allows the image to be hidden again. Includes `gallery.css` for styling the modal dialogs and backdrop, `gallery.js` manages modal dialog interactions.
{% include "partials/gallery.njk" %}
## Loop through images without additional interactivity:
<ul class="gallery" role="list" style="padding: 0;">
{%- for item in gallery -%}
<li>{% image item.image, item.alt %}</li>
{%- endfor -%}
</ul>

View file

@ -1,45 +0,0 @@
---
title: 'Eleventy Excellent 2.0'
description: I created this starter after I saw Andys talk and studied the source code for **buildexcellentwebsit.es.** I quickly came to the conclusion that this is the way I want to build all my websites from now on! It's so great. I know many of you feel the same way.'
discover:
description: "I used markdown Syntax in the description, this is why I set this other description to be used in the meta description and the blog schema."
date: 2024-02-01
---
I changed so much, that documenting everything will be hard. I will try and name the most important changes in the next few weeks.
## Maybe a quick "why" first
I created this starter after I saw [Andy's talk](https://eleventy-excellent.netlify.app/about/#watch-the-talk) and studied the source code for buildexcellentwebsit.es.
I quickly came to the conclusion that this is the way I want to build all my websites from now on! It's so great. I know many of you feel the same way.
I had already accumulated a lot of opinions, files and basic settings from my previous Eleventy projects, and to make it easier for me to start a new project in the future, I combined everything in this starter. The name is a tribute to its origin:
> "Go Forth And Build **Excellent** Websites"!
When that was finished, I thought it was only fair to make it easily accessible to others, and at the end of 2022 I registered the starter with the [official stater projects](https://www.11ty.dev/docs/starter/).
What I didn't count on, was _how many_ people would actually go and use the starter.
So many of you have also contacted me or contributed something.
## I wanted to make the starter better
I have since made sure that everything stays fairly updated, fixed a few bugs and added a few features -- but I haven't quite dared to change the base too much, now that so many others were involved.
The thing is, I have learned **lots of new things** and changed my mind about other stuff like naming or organization in the last year and a half. Whenever I begin a project now, I still turn to this starter -- but I modify _a lot_ before I get started. This goes above all for the organization and naming of files and folders, modern CSS, and better accessibility.
You will see that many things are new and different, but better! And that the basic character is still the same.
I will try and take some time to document important changes so you can upgrade more easily.
[I have kept v1 in a separate branch.](https://github.com/madrilene/eleventy-excellent/tree/v1)
## Plans for the future
- I will change everything to ES modules as soon as Eleventy v3 with ESM support is stable.
- I might bring back the drawer menu as something to opt in (**Update:** I did this already, see "[Get started](/get-started/#navigation)").
- Lots of small fixes, no doubt.
**Thank you and let's build more excellent websites!**

View file

@ -1,30 +0,0 @@
---
title: 'Eleventy Excellent 3.0'
description: "It's been a few months, and I have decided to change things again, which probably makes the starter even more opinionated. 🤷 Eleventy Excellent 3.0 now uses ESM, has a new config structure and uses web components."
discover:
description: "I have decided to change things again: Eleventy Excellent 3.0 now uses ESM, has a new config structure and uses web components."
date: 2024-06-03
---
It's been a few months, and I have decided to change things again, which probably makes the starter even more opinionated 🤷. For those who prefer the previous version, Version 2 will remain accessible in its own branch.
**Core changes:**
- ESM! I originally wanted to wait for the beta version of Eleventy 3.0, but the alpha version works absolutely fine, so I decided to go for it.
- a new font for the body (base) text: Inclusive Sans. Only has Regular 400 and Regular 400 italic for now, so bold uses the display font.
- A new config structure (turns out I am the [Eleventy config person!](https://front-end.social/@lene/112530901535448479)). I also decided to have everything inside the `src` folder. [More about that in the docs](/get-started/#config).
- some new filters, for having markdown format in the frontmatter, and for sorting.
- there is now a "setup" directory inside of the `_config` folder, for automatic favicon creation and to add the screenshots to the "built with" section. They are triggered by new scripts in `package.json`. See also ["Favicons" in the docs](/get-started/#favicons).
- SVGs are now in `src/assets/svg`, and there is a new SVG shortcode to include them. I also explain this [in the SVG section](/get-started/#svg).
- I now actively use Eleventy's plugins [`WebC`](https://www.11ty.dev/docs/languages/webc/) (for components), the [bundle plugin](https://github.com/11ty/eleventy-plugin-bundle) and[`<is-land>`](https://github.com/11ty/is-land).
- I made small CSS changes everywhere - and introduce a new structure, [also explained in the docs](/get-started/#css).
- JavaScript handling [changed a lot, too](/get-started/#javascript).
- Also: improvements in terms of organization and naming.
I don't consider myself a JavaScript person, and I still struggle to fully grasp WebC. So, if you have any suggestions or improvements, in particular to the WebC and web components code, please don't hesitate to reach out or send a PR.
**Plans for the future:**
This starter was meant to be hosted on Netlify, and I'd like to change that so that it works with any host without much extra effort.
I hope you enjoy the new version! 🌟
And, should you decide to upgrade -- sorry for not making this easier for you. I hope that you don't face too many difficulties!

View file

@ -1,14 +0,0 @@
---
draft: true
title: 'A draft'
description: "This is a draft. It will not be included in the final build."
date: 2024-07-21
---
In development (`npm run start`), you can preview posts that won't be published in production (`npm run build`) by setting `draft: true` in the front matter.
```yaml
---
draft: true
---
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 KiB

View file

@ -1,202 +0,0 @@
---
title: 'Post with an image'
description: "We can use Markdown, Nunjucks shortcodes or pure HTML to add images to posts and pages."
date: 2025-01-09
tags: ['image', 'feature']
---
Using the powerful [Eleventy Image plugin](https://www.11ty.dev/docs/plugins/image/), we have three ways to optimize images: <a href="#html-transform">HTML Transform</a>, <a href="#markdown-syntax">Markdown syntax</a>, and <a href="#nunjucks-shortcodes">Nunjucks shortcodes</a>.
<a name="html-transform"></a>
## HTML Transform
Transforms any `<img>` or `<picture>` tags in HTML files as a post-processing step. Find the default settings directly in `eleventy.config.js`.
```html
<img src="./co-located-image.jpg" alt="alt text">
<img src="/assets/images/absolute-path-image.jpg" alt="alt text">
```
We can pass in overrides for every instance and use attributes. By default all images are set to be lazy loaded, but we can override this by directly setting `loading="eager"` and `decoding="sync" `on the `<img>` element.
Another thing to note is the `widths: ['auto']` setting, which by default only includes the original size image. We can set the dedicated `widths` to be used by adding `eleventy:widths="800,1200"` on the element. For images with [Markdown syntax](/blog/post-with-an-image/#markdown-syntax), I set fixed `widths` so we don't need to set a value on every instance.
`sizes` defaults to `auto`, which is applied to all lazy loading images. For eager-loading images, the value is equivalent to `100vw` See: https://github.com/whatwg/html/pull/8008. We can _still_ overwrite this, by setting the `sizes` attribute directly on the `<img>` element, with something specific like `sizes="(max-width: 615px) 50vw, 100vw"`.
```html
<img src="./co-located-image.jpg" alt="alt text" eleventy:widths="200,600" loading="eager" decoding="sync">
```
<img src="./asturias-1.jpg" alt="A picturesque valley showcasing majestic mountains and lush forests, creating a serene and captivating landscape" eleventy:widths="200,600" sizes="(max-width: 615px) 50vw, 100vw" loading="eager" decoding="sync">
**Extra benefit:** we can use both relative and absolute image sources.
One downside is that it comes with a higher build cost due to the post-processing step.
More info: https://www.11ty.dev/docs/plugins/image/#html-transform
## Markdown syntax
This also uses [Image HTML Transform ](https://www.11ty.dev/docs/plugins/image/#html-transform).
The markdown sytnax for images creates the `<img>` element the plugin is looking for, and then transforms it to the `<picture>` element (if more than one format is set).
In `src/_config/plugins/markdown.js` I customized the Markdown rendering for images slightly. What normally would become a `title` attribute is used to create the caption (`<figcaption>` within a `<figure>` element). Note that I set a fixed `widths` value instead of `auto` as the default.
```markdown
![alt text](/path/to/image 'caption text')
![Close-up...](/assets/images/gallery/asturias-4.jpg) 'I used a portrait lens for this one'
```
![Close-up with unfocused background of a vibrant large blue butterfly gracefully perched on a delicate flower amidst lush green gras](/assets/images/gallery/asturias-4.jpg 'I used a portrait lens for this one')
We can also add custom attributes here ([Kudos to Aleksandr](https://www.aleksandrhovhannisyan.com/blog/eleventy-image-transform/)), to overwrite the default `widths`, have the image eagerly loaded, or add a `class` attribute, etc.
```markdown
![alt text](/path/to/image){attrs}
![Close-up...](/assets/images/gallery/asturias-2.jpg){loading="eager" decoding="sync" eleventy:widths="400" class="grayscale"}
```
![Close-up of a delicate white flower with a yellow center, surrounded by green leaves](/assets/images/gallery/asturias-2.jpg){loading="eager" decoding="sync" eleventy:widths="400" class="grayscale"}
## Nunjucks shortcodes
### Positional parameters Shortcode
The positional parameters shortcode is the legacy approach and requires the arguments to be **passed in the correct order**.
The most basic version contains only the path to the image.
{% raw %}
```jinja2
{% image "path to image" %}
```
{% endraw %}
All skipped parameters are set to their default values: an empty string if no `alt` text is passed, `loading = 'lazy'`, the `<picture>` element gets its set of images from the default `widths=[650,960,1400]` and compares to a condition of `sizes="auto"`, formats are `['avif', 'webp', 'jpeg']`.
We can pass in manually all the conditions, and add `null` to skip. The arguments include classes for the outer container ( `<picture>` or `<figure>` element), and for the `<img>` element.
{% raw %}
```jinja2
{% image "path to image", "alt text", "caption text", "eager", "container class names", "img class names", [200, 400], "(min-width:30em) 50vw, 100vw", ['webp', 'jpeg'] %}
{% image "path to image", "alt text", null, "eager" %}
```
{% endraw %}
{% image "/assets/images/gallery/asturias-3.jpg", "A traditional Asturian village with it's raised granaries, surrounded by lush green hills and mountains", "An example for the positional parameters shortcode.", "lazy", "text-center", "grayscale", [200, 400], "(min-width:30em) 50vw, 100vw", ['webp', 'jpeg'] %}
**Example:** predefine `widths` and `sizes` using Nunjuck's `set` tag or front matter fields, and dynamically get the image path, like I do in the "[Built with](/blog/built-with/)" template.
{% raw %}
```jinja2
{% set widths = [400, 520] %}
{% set sizes = '(max-width: 615px) 50vw, 100vw' %}
{% image "/assets/images/screenshots/" + site.filename + ".jpg", site.name, null, "lazy", null, null, widths, sizes %}
```
{% endraw %}
### Named Parameters Shortcode
Remembering the order of the arguments is a bit of a pain, so I added a second shortcode: `imageKeys`.
This shortcode allows us to specify parameters in any order or only include the ones we need to customize. We need to pass the parameters as a `JSON` object with the key-value pairs.
{% raw %}
```jinja2
{% imageKeys {
"src": "/assets/images/gallery/asturias-3.jpg",
"alt": "A traditional Asturian village with it's raised granaries, surrounded by lush green hills and mountains",
"caption": "An example for the named parameters shortcode.",
"loading": "lazy",
"containerClass": "text-center",
"imageClass": "grayscale",
"widths": [200, 400],
"sizes": "(min-width:30em) 50vw, 100vw",
"formats": ["webp", "jpeg"]
} %}
```
{% endraw %}
{% imageKeys {
"src": "/assets/images/gallery/asturias-3.jpg",
"alt": "A traditional Asturian village with it's raised granaries, surrounded by lush green hills and mountains",
"caption": "An example for the named parameters shortcode.",
"loading": "lazy",
"containerClass": "text-center",
"imageClass": "grayscale",
"widths": [200, 400],
"sizes": "(min-width:30em) 50vw, 100vw",
"formats": ["webp", "jpeg"]
} %}
**Example:** if we only need to customize `alt` text and `sizes`:
{% raw %}
```jinja2
{% imageKeys {
"sizes": '(min-width:30em) 50vw, 100vw',
"alt": "A traditional Asturian village with it's raised granaries, surrounded by lush green hills and mountains",
"src": "/assets/images/photo.jpg"
} %}
```
{% endraw %}
The shortcodes are defined in `src/_config/shortcodes/image.js`. They also set `slot="image"` on their container element, so they can be used with any WebC component that contains a `<slot name="image"></slot>`, see `src/_includes/webc/custom-card.web` for example.
Since we are using them alongside the <a href="#html-transform">Image HTML Transform</a> method, the shortcodes add `eleventy:ignore` to the `<img>` attributes so the images arent processed twice.
## Comparing Shortcode and HTML Transform
The shortcode can be much terser than the HTML syntax, while the HTML syntax is more readable and has a well known structure.
**These two approaches produce (almost) the same output:**
{% raw %}
```jinja2
{% image image, alt or "", credit, "eager", "feature", "grayscale" %}
<figure class="feature">
<img src="{{ image }}" alt="{{ alt or '' }}" loading="eager" decoding="sync" class="grayscale">
{% if credit %}
<figcaption>{{ credit }}</figcaption>
{% endif %}
</figure>
```
{% endraw %}
{% set image = '/assets/images/gallery/asturias-1.jpg' %}
{% set alt = 'A picturesque valley showcasing majestic mountains and lush forests, creating a serene and captivating landscape' %}
{% set credits = ['Example image using the positional shortcode', 'Example image using the HTML syntax'] %}
{% for credit in credits %}
{% if loop.index == 1 %}
{% image image, alt or "", credit, "eager", "feature", "grayscale" %}
{% else %}
<figure class="feature">
<img src="{{ image }}" alt="{{ alt or '' }}" loading="eager" decoding="sync" class="grayscale">
{% if credit %}
<figcaption>{{ credit }}</figcaption>
{% endif %}
</figure>
{% endif %}
{% endfor %}
More:
- https://www.11ty.dev/docs/plugins/image/
- https://www.youtube.com/watch?v=e0OHgC677ec
- https://www.aleksandrhovhannisyan.com/blog/eleventy-image-transform/
- https://coryd.dev/posts/2024/setting-up-image-transforms-in-eleventy

View file

@ -1,87 +0,0 @@
---
title: 'Eleventy Excellent 4.0'
description: "Time for a new version with a lot of breaking changes! Have fun everybody."
date: 2025-01-11
---
A new version is here! This includes a bunch of breaking changes.
Again I am changing the body font for this update, this time it's [Atkinson Hyperlegible](https://www.brailleinstitute.org/freefont/).
## New Image handling
I have been clinging to my image shortcode for too long. With the [latest major version of Eleventy Image](https://github.com/11ty/eleventy-img/releases/tag/v6.0.0) I decided it's finally time to also include the transform method, because it is awesome.
That alone would not be a breaking change, but I decided to change the existing Nunjucks image shortcode a bit. If you use the shortcode beyond the container class, you must adjust your code to these changes:
```js
( src,
alt = '',
caption = '',
loading = 'lazy',
containerClass,
imageClass,
widths = [650, 960, 1400],
sizes = 'auto',
formats = ['avif', 'webp', 'jpeg']
) => { ...
```
- **Breaking:** `widths` is now passed in _before_ `sizes` (because I change this value much more often).
- **Breaking:** `imageClass` is a new paramteter dedicated to the `<img>` element, while `containerClass` is for the container (`<figure>` or `<picture>`), as before.
- also new: for all images you can start the path relative to the input folder (drop `./src` in the path, though it is compatible with `./src` being present)
Using the transform comes with the great advantage, that you can now use co-located images with the HTML and Markdown sytnax. 🎉
For a detailed overview of the new image possibilities [see the dedicated blog post](/blog/post-with-an-image/).
## Cascade layers
[Inspired by Mayank's post](https://mayank.co/blog/css-reset-layer/), Ive transitioned to using [cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers), instead of using the `:where()` pseudo-class to create low-specificity selectors for resets and compositions.
- The global CSS bundle is now organized with cascade layers.
- The local CSS bundle, used for per-page or component-specific styles, does not utilize cascade layers. As a result, all CSS blocks included have a higher specificity than global styles, regardless of the selector specificity in the global CSS bundle.
**Breaking:** The "inline" bundle is now called "local", as this made more sense: all bundles are inlined.
## New color system
Run `npm run colors` after defining your base color values in `src/_data/designTokens/colorsBase.json`. This will generate or update the `colors.json` file in the same directory.
- Colors under `shades_neutral` or `shades_vibrant` are converted into scalable palettes. This is not very elaborate, use a value more or less in the middle of the scale. Happy to receive suggestions for improvements.
- Colors listed under `standalone` and `light_dark` are left as they are, `light_dark` items output a second "subdued" version optimized for dark themes.
```json
// this creates a palette with shades of green, 100 to 900
{
"shades_vibrant": [
{
"name": "green",
"value": "#008000"
}
]
}
```
`src/assets/css/global/base/variables.css` changed a lot, as I now use new color names. I also dropped the `@supports` blocks for `color-mix()` and the relative color syntax -- not because they aren't great, but I just perceived the whole file as too complex. Now JavaScript does the step of creating subdued colors for the dark theme.
I also considered using the new `light-dark()` CSS function instead of the repetitive code for `prefers-color-scheme` and `data-theme=“dark”`, but the browser support is still too low.
**Breaking:**: `src/assets/css/global/base/variables.css` changed. You must adapt your colors in `src/_data/designTokens/colorsBase.json` if you want to use the `npm run colors` script.
You can also just completely skip that and define your colors directly in `colors.json` (I recommend deleting the `colors` command in `package.json` in this case, so you don't unitentionally overwrite your work).
[More about colors here](/get-started/#design-tokens).
## New button styles
Inspired by [Andy's article](https://piccalil.li/blog/how-i-build-a-button-component/), the button styles changed. As the article explains that very well, I won't say much more about it.
## Other new features and changes
- `border-radius` became a design token used by the Tailwind config, to be set in `src/_data/designTokens/borderRadius.json`.
- new `3XS` spacing value in `src/_data/designTokens/spacing.json`.
- new `grid` composition layout `data-layout='thirds`.
- new OG images template. As it uses `meta.siteName` next to the 11ty Logo, you might have to adjust the template for that `src/common/og-images.njk`.
Let me know if you have any questions or issues with the update.
I am happy to help you out. Maybe you'll want to wait a bit, as I will add some more fixes, no doubt.

View file

@ -1,7 +1,7 @@
---
title: 'Gasheyes Creek'
description: "A story about a creek."
date: 2025-11-11
date: 2026-01-01
tags: ['place']
eleventyNavigation:
key: Oakington Peninsula