Tags
Auto-generated tag pages built from a custom collection — every demo tag gets its own page with zero manual wiring.
Live Implementation
Every tag below is generated from the demoTags collection — add a new tag to any demo's front matter and a page for it appears here automatically:
How It Works
Every demo’s front matter has a tags array, like ["css", "javascript"]. A directory data file (src/demos/demos.json) also stamps a structural "demo" tag onto every file in that folder, and Eleventy merges those two arrays together, so a demo’s final tag list ends up as ["demo", ...whatever you wrote].
A custom collection called demoTags walks every demo, pulls out the non-structural tags into a Set (which dedupes and sorts them for free), and hands back the list. One paginated template, tags.njk, then asks Eleventy to spit out one page per tag, landing at /demos/tags/<tag>/.
Folder Structure
src/_11ty/collections/demoTags.js ← builds the unique tag list
src/tags.njk ← paginated template, one output per tag
src/_includes/components/tag-list.njk Important Files
src/_11ty/collections/demoTags.js
export default function demoTags(collectionApi) {
const items = collectionApi.getFilteredByGlob("src/demos/*.md");
const tagSet = new Set();
items.forEach((demo) => {
(demo.data.tags || []).forEach((tag) => {
if (tag !== "demo") tagSet.add(tag);
});
});
return [...tagSet].sort();
} src/tags.njk
---
pagination:
data: collections.demoTags
size: 1
alias: tag
permalink: "/demos/tags/{{ tag | slugify }}/"
eleventyExcludeFromCollections: true
eleventyComputed:
title: "{{ tag }}"
description: "Every demo tagged “{{ tag }}”."
---
{% extends "layouts/base.njk" %}
{% import "components/demo-card.njk" as demoCardC %}
{% set matching = collections.demos | byTag(tag) %}
{% block content %}
<div class="wrapper">
<header class="page__header">
<p class="page__eyebrow"><a href="/demos/">← All demos</a></p>
<h1 class="page__title">Tag: {{ tag }}</h1>
<p class="page__lede">{{ matching.length | pluralize("demo") }} tagged “{{ tag }}”.</p>
</header>
<div class="demo-grid">
{% for demo in matching %}
{{ demoCardC.demoCard(demo) }}
{% endfor %}
</div>
</div>
{% endblock %} Notes
- Add a brand-new tag to any demo’s front matter and its page just appears on the next build. Nothing else to touch.
- Tag pages reuse the same
demoCardmacro as the main/demos/listing, so they look consistent without any extra work.