Listings & pagination

Give a collection a list template and Baudelaire generates an index page at /{collection}/ listing its members:

collections {
  features sort="order" list="list.typ"
}

That single page holds every member: no pagination. This site’s features index is exactly this: one page, all features, in order.

Add paginate = N when a collection is long enough to split:

collections {
  blog sort="date" reverse=#true paginate=5 list="list.typ"
}

Now Baudelaire generates /blog/, /blog/page/2/, /blog/page/3/, and so on, each listing five entries with previous and next links. Pagination is just the splitting modifier on top of a listing: the same list template renders both.

The page segment in the URL is configurable per collection with prefix:

collections {
  blog paginate=5 prefix="p"    // → /blog/p/2/
  news paginate=5 prefix=""     // → /news/2/
}

An empty prefix drops the segment entirely, numbering pages directly under the collection.

The list template receives the page’s entries and its navigation as structured data, not HTML:

#let list(page, body) = {
  for entry in page.frontmatter.entries {
    // entry.url, entry.label, entry.date, entry.note, entry.extra
  }
  let nav = page.frontmatter.nav   // nav.prev, nav.next
}

Each entry carries the source page’s date and its full extra frontmatter, so a blog index can show dates and summaries while a tag index shows counts, all from one template. Because it is a template, paginated indexes look like the rest of your site. This site’s blog is paginated exactly this way.