Statac

Write

Lists, tags and series

A list gathers posts for a page to show: Statac keeps one for the site, each folder, each tag and each series, and a page can make its own.

What is a list?

List Holds Order Its page
The site Every post Newest first content/index.md, the home page
A folder Every post beneath it, however deeply filed Newest first The folder’s index.md
A tag Every post carrying it Newest first /tags/rust/ for Rust
A series Every post in it Oldest first, so it reads in order /series/series-1/ for Series 1
A list of your own The posts a posts: line chooses Newest first The page with the line

A post is a page with a date, in its front matter or at the start of its file’s name. A page with no date, such as an about page, is in no list of posts.

On a site in several languages, each language keeps its own: lists in each language.

The page at a list’s address

The page at a list’s address speaks for it: a folder’s index.md, or content/tags/rust.md at /tags/rust/. Its writing introduces the list, and its front matter carries the list’s settings:

Line What it does
order Which way the posts run.
numbered false where the numbers opening the names are part of them.
posts_per_page, index_page How many posts each page shows, and whether any is published.
feed Where the list’s feed goes, or false for none.
posts, each A list of your own.

Where no page of yours stands there, Statac makes one, with no writing and no title: headline(page) calls it by the list’s name.

With no layout of its own, the page is built with templates/folder.html, or templates/home.html for the home page. A layout handed down doesn’t reach it.

A folder’s list

In content/posts/index.md:

---
title: Posts
order: oldest first
---
The posts, oldest first.

content/posts/ lists every post beneath it, and content/posts/2026/ that year’s.

A folder at the top of content/ with no index.md gets a page from Statac. A folder inside another has a page only by its own index.md.

A folder holding an index.md and nothing else is one page, not a list.

Tags

In a post’s front matter:

tags: [Rust, Go]

Statac never changes the capitals of a tag.

To introduce a tag, write a page at its address, such as content/tags/rust.md. A template names a tag’s page by its list:

<title>{{ headline(page) }}</title>
<h1>Posts tagged {{ page.list.name }}</h1>

In statac.yaml, for the pages Statac makes for tags and series:

Setting What it does Unless you say
tags.permalink, series.permalink Where the pages go: tags.permalink: /topics/{slug}/. /tags/{slug}/, /series/{slug}/
tags.pages, series.pages false makes no pages. The lists still work in templates. true
tags.slugs, series.slugs A name’s own part of the address. None
tags.slugs:
  C++: cpp

Series

In a post’s front matter:

series: Series 1

A post is in one series at most, and walks it.

Order

On a list’s page:

order: oldest first

Posts of the same day with no time come A to Z by file name. Give one a time to choose its place: date: 2026-10-05 08:00.

pages.order: oldest first in statac.yaml turns every list. In a folder’s index.md, it turns the lists inside the folder, not the folder’s own.

Numbered folders

File Place in the list Address
content/days/01-day-one.md 1 /days/day-one/
content/days/02-day-two.md 2 /days/day-two/
content/days/03-day-three.md 3 /days/day-three/

Where every page in a folder opens its name with a number and a hyphen, its list holds every page, dated or not, in the order of the numbers. The numbers are left out of the addresses.

Where the numbers are part of the names, in the folder’s index.md:

numbered: false

To order a folder by hand, list its pages in its index.md by the names in their addresses:

order: [day-one, day-two, day-three]

Pages the list leaves out follow in their usual order.

Pages of a list

A list’s page shows ten posts. Any more go on later pages beneath it: /blog/page/2/ has the next ten, built with the same template.

Setting Written in What it does Unless you say
posts_per_page statac.yaml for every list, or a list’s page for that list How many posts each page shows. 0 shows every post on one page. 10
later_pages statac.yaml only Where the later pages go, as a pattern. {list}page/{n}/
index_page A list’s page false publishes nothing at the list’s address, and no later pages. The list still works in templates. true

In statac.yaml:

later_pages: "{list}{n}/"

This puts page 2 of /blog/ at /blog/2/. The pattern opens with {list}, holds {n} once and ends with /.

A later page carries the list’s title, summary, fields and layout, and none of its writing. A page that isn’t HTML, such as a feed, shows every post on one page.

On a list’s pages, page.previous and page.next walk those pages.

Previous and next

{% if page.next %}<a href="{{ page.next.url }}">{{ page.next.title }}</a>{% endif %}

page.previous and page.next are the pages either side of this one, in the order a reader meets them: in a list running newest first, page.next is the older post. A post at either end has no previous, or no next, so ask first.

A post walks:

  • its series, where it is in one;
  • otherwise, the folder holding it at the top of content/: a post in content/posts/2024/ walks all of content/posts/;
  • or, for a post directly in content/, every post on the site.

neighbours: chooses another:

neighbours: Walks
site Every post on the site.
folder The folder at the top of content/ holding the page, even where it is in a series.
series Its series. A post in none has no previous or next.
false None.

pages.neighbours: in a folder’s index.md hands it to every page inside.

{% for post in related(page) %}
<a href="{{ post.url }}">{{ headline(post) }}</a>
{% endfor %}

related(page) gives the posts sharing a tag with the page, those sharing the most first.

Lists made with posts: and each:

---
title: Rust in the blog
posts: site.posts | in("blog") | tagged("Rust")
---

posts: gives a page a list of its own: every post, narrowed by these filters.

Filter Keeps
tagged("Rust") The posts carrying the tag, whatever its capitals.
in("blog") The posts in a folder, by its name or its path under content/.
where("field", "value") The posts whose field holds the value, or a list holding it among others. year, month and day ask about the post’s date.

The same filters work on any list of pages in a template, and newest_first puts one in date order.

A page for each post

In content/print.md:

---
title: Printable posts
each: site.posts | tagged("Rust")
permalink: /print/{slug}/
layout: print
index_page: false
---

each: makes a page for each post it chooses: here /print/post-1/, built with templates/print.html.

Line What it does
each site.posts, and any of the filters a posts: line takes.
permalink Needed. The pattern for each page’s address, filled in from the post: {slug}, {name}, {folder}, {year}, {month}, {day}, or any field of the post, such as {isbn}.
layout The template for the pages made. The page with each: is built with templates/folder.html.
index_page false publishes nothing at the page’s own address.

The template sees the post as page.post: page.post.title, page.post.date, page.post.url. The page made is not the post: page.title and page.url are its own, it has no date and no other list holds it. page.list.pages on the page with each: holds the pages it made.

each: also makes a page for each item of a data file: pages made from data.

Drafts and posts waiting for their day

---
title: Post 1
draft: true
---

A page with draft: true is a draft. A post dated after today, on the site’s own clock, is waiting for its day.

statac serve
Showing 1 draft and 1 post waiting for its day, which `statac build` leaves out.

statac serve shows both and marks each one. To see exactly what a build would publish:

statac serve --no-drafts

statac build leaves both out: neither is published, listed or in a feed. A waiting post is published by the first build on or after its day.

To build them as if published:

statac build --drafts

--today=2026-10-05 builds the site as it will be on that day. Serving and building have the rest.

Pages without titles

For short notes with no title, in the folder’s index.md, here content/notes/index.md:

---
pages.untitled: true
---

Every page in the folder is handed it; in statac.yaml, every page of the site. headline(page) then calls each one by its date:

The page has headline calls it by
A title, or an opening # heading That, as any page is.
A date The date, as the site writes dates: 4 October 2026.
No date Its summary, else its opening words, else its address.

One page says the same for itself with untitled: true, or untitled: false in such a folder.

Lists in templates

{% if page.list.word == "tag" %}
<h1>Posts tagged {{ page.list.name }}</h1>
{% else %}
<h1>{{ page.list.title }}</h1>
{% endif %}
{% for post in page.posts %}
<p><a href="{{ post.url }}">{{ headline(post) }}</a></p>
{% endfor %}
{% if page.list.pager | length > 1 %}
<p>Page {{ page.number }} of {{ page.list.pager | length }}</p>
{% endif %}

Every list answers the same names:

Name What it holds
name The folder’s, tag’s or series’ name.
title The title of its page, or else its name.
url The address of its page.
page Its page, where it has one.
posts All its posts, in its order.
pages Its posts, then the pages it would hold were they dated.
pager Its pages, first to last, each with its number and url. A list with no page of its own has none.
feed The address of its feed, or nothing where it has none.
word Which kind of list it is: site, folder, tag, series, or chosen for one a page makes with posts: or each:.
order newest first or oldest first, or nothing where numbers or an order: list place its posts.

The site’s lists, and the page’s:

Name What it holds
site.posts Every post, newest first.
site.pages Every page the site publishes, in the order of their addresses. Redirects are not in it.
site.tags, site.series Every tag and every series, A to Z.
site.folders Every folder with a page of its own, in the order of their addresses. A site’s navigation is a loop over it.
page.tags, page.series The page’s tags, and its series. {% if "Rust" in page.tags %} asks whether it carries a tag.
page.folder The folder the page is filed in.
page.list, page.posts On a page that speaks for a list, the list, and the posts this page of it shows. Other pages have none.
page.number On a page that speaks for a list, which of its pages this is, from 1.
page.previous, page.next The pages either side of this one.

On a site in several languages, see each language in templates.

A new site’s own snippets for lists are in the home page and the lists.

Where next?

Something unclear or wrong? Open an issue on GitHub.