Collections and Pagination
Content Collections and Pagination
Pages can define content collections via a content block in frontmatter. The collection specifies which pages to include, how to filter and sort them, and how many to show per page. The result is exposed as page.collection in the template context, with pagination metadata in page.pagination.
Collection Frontmatter
--- title: Blog template: blog content: items: "@self.children" # Source: children of current page order: by: date # Sort field: date, title, order, url dir: desc # Direction: asc or desc limit: 10 # Items per page (enables pagination) filter: tags: [rust] # Only pages with these tags author: "John Doe" # Only pages by this author published: true # Only published pages (default) custom: # Only pages with these frontmatter values category: praxis ---
filter.custom matches your own frontmatter keys. A page is kept when it matches every key you list: its value equals the one you give, or, when the page’s value is a list, any element equals it. This is how you group pages by an author-defined key – a category, a product type, an event track – without turning it into a tag.
The match is by value and type: a YAML string matches a string, a number a number, a boolean a boolean. featured: true in the filter matches a page’s featured: true but not featured: "true", and year: 2024 does not match year: "2024". Write the filter value the same way you write it in the page’s frontmatter.
The items field currently supports @self.children to collect child pages of the current page. On a site with several languages, the children are the pages of the current page’s language, as page.children and page.siblings are.
Sorting
order.by accepts date, title, order, or url, with dir set to asc or desc.
Sorting by date is chronological, not alphabetical: each page’s date is parsed into a calendar date before comparison, so every format Accent accepts sorts in true date order – ISO (2026-06-14, and non-zero-padded forms like 2026-5-24), US (06/14/2026), European (14.06.2026), and long or short month (June 14, 2026, Jun 14, 2026). You do not need to zero-pad or normalise dates for them to sort correctly. Pages whose date is missing or unrecognised sort first in ascending order (last in descending); ties keep a stable, deterministic order.
Collection Template
Each item in page.collection has the same properties as pages in children or siblings (title, url, date, author, lead, tags, order). It also carries custom, a mapping of the page’s own frontmatter keys, so a listing can show or test them: {% for p in all_pages if p.custom.category == "praxis" %} or {{ post.custom.subtitle }}. The same custom mapping is on all_pages, page.children, page.siblings, taxonomy.pages, and recent_documents().
{% for post in page.collection %}
<article>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
{% if post.lead %}<p>{{ post.lead }}</p>{% endif %}
{% if post.date %}<time>{{ post.date }}</time>{% endif %}
{% if post.tags %}
<div class="tags">
{% for tag in post.tags %}<a href="{{ tag_url(tag) }}">{{ tag }}</a>{% endfor %}
</div>
{% endif %}
</article>
{% endfor %}
Pagination
When content.limit is set, Accent CMS automatically paginates the collection. Pagination metadata is available in page.pagination:
| Property | Type | Description |
|---|---|---|
page.pagination.current_page | int | Current page number (1-based) |
page.pagination.total_pages | int | Total number of pages |
page.pagination.total_items | int | Total number of items in the collection |
page.pagination.items_per_page | int | Items shown per page |
page.pagination.prev_url | string/none | URL to the previous page (none on page 1) |
page.pagination.next_url | string/none | URL to the next page (none on last page) |
Pagination URLs append /page/{num} to the page URL, for example /blog/page/2. Page 1 is the page URL itself. The same URL works under accent serve and on a static host, because it is the path the build writes the page to. An older link in the /blog/page:2 form redirects permanently to /blog/page/2 under accent serve.
Because /page/{num} is pagination, give a paginated page no child page named page with numbered children: accent serve shows the child page, while the build writes both to the same file.
{% if page.pagination %}
<nav class="pagination" aria-label="Pagination">
{% if page.pagination.prev_url %}
<a href="{{ page.pagination.prev_url }}">Previous</a>
{% endif %}
<span>Page {{ page.pagination.current_page }} of {{ page.pagination.total_pages }}</span>
{% if page.pagination.next_url %}
<a href="{{ page.pagination.next_url }}">Next</a>
{% endif %}
</nav>
{% endif %}
Static Build
The accent build command generates HTML files for all pagination pages. Page 1 is written to output/{path}/index.html, and subsequent pages to output/{path}/page/{num}/index.html, the path the pagination links name, so they work on any static host.
Content Relationships
Pages can define named relationships to other pages via the relations frontmatter field. Each relationship is a named list of page references that are resolved into full PageMetaContext objects at render time.
Relations Frontmatter
--- title: Advanced Patterns relations: series: ["part-1", "part-2", "part-4"] related: ["/docs/advanced", "/blog/deep-dive"] prerequisites: ["/docs/getting-started"] ---
References can be:
- Absolute URLs: Starting with
/, resolved directly (e.g.,/docs/getting-started) - Relative slugs: Resolved from the current page’s parent URL (e.g., on
/blog/part-3, the slugpart-2resolves to/blog/part-2)
Broken references (pointing to non-existent pages) are logged as warnings and omitted from the result. Relationship names are arbitrary strings defined by the content author.
Relations in Templates
Resolved relations are available as page.relations.<name>, where each entry is a page metadata object with title, url, date, author, lead, tags, and order.
Series navigation:
{% if page.relations.series %}
<nav class="series-nav">
<h3>In this series</h3>
<ol>
{% for part in page.relations.series %}
<li>
{% if part.url == page.url %}
<strong>{{ part.title }}</strong> (current)
{% else %}
<a href="{{ part.url }}">{{ part.title }}</a>
{% endif %}
</li>
{% endfor %}
</ol>
</nav>
{% endif %}
Related articles sidebar:
{% if page.relations.related %}
<aside class="related">
<h3>Related Articles</h3>
<ul>
{% for article in page.relations.related %}
<li><a href="{{ article.url }}">{{ article.title }}</a></li>
{% endfor %}
</ul>
</aside>
{% endif %}
Prerequisites notice:
{% if page.relations.prerequisites %}
<div class="prerequisites">
<p>Before reading this, you should be familiar with:</p>
<ul>
{% for prereq in page.relations.prerequisites %}
<li><a href="{{ prereq.url }}">{{ prereq.title }}</a></li>
{% endfor %}
</ul>
</div>
{% endif %}
The default theme template automatically renders series, related, and prerequisites relations when present.