A page for every tag in Stati

One [tag].md template, URLs from Stati's slugify, and links that match them.

SNP 148 #415 Filed stati eta

yaml
---
# site/blog/tags/[tag].md
title: 'Posts tagged {tag}'
description: 'Everything I wrote about {tag}.'
generate:
  from: tags
---
eta
<% /* In site/blog/tags/layout.eta */ %>
<h1><%= stati.page.title %></h1>
<ul>
  <% for (const post of stati.generated.items) { %>
    <li><a href="<%= post.url %>"><%= post.frontMatter.title %></a></li>
  <% } %>
</ul>

The links to them, from a post:

eta
<% for (const tag of stati.page.tags ?? []) { %>
  <a href="<%= `/blog/tags/${stati.slugify(tag)}` %>">#<%= tag %></a>
<% } %>
  • The template never becomes a page itself. It becomes /blog/tags/css, /blog/tags/node-js and so on, one for each tag of the posts in /blog.
  • The keys go through Stati's slugify: CSS is css, Node.js is node-js. {tag} in the front matter is the tag as written (CSS), and stati.generated has both, as key and label.
  • generate: { from: tags, paginate: 10 } splits the long ones into pages, read from stati.pagination.items.
  • A tag's page disappears with the last post that has the tag. Tags a beforeAll hook adds get no page, because the pages are made before the hook runs.

For a page of all the tags, take one outside the blog folder, such as site/tags.md with collection: /blog in its front matter, and count them from pagesByTag:

eta
<% const byTag = stati.collection?.pagesByTag ?? {}; %>
<% for (const tag of Object.keys(byTag).sort()) { %>
  <a href="<%= `/blog/tags/${stati.slugify(tag)}` %>"><%= tag %> (<%= byTag[tag].length %>)</a>
<% } %>

An index.md in blog/tags/ would turn up among the posts in the blog's own listing.

In the Stati docs: Generated pages, Placeholders and Linking to generated pages.