Documentation

Last updated in git: 2026-06-11

Cross-linking pages with all_pages

Every template in markdown-mode sites has access to a global all_pages variable — a list of every .md page in the site with its full frontmatter. This lets any layout pull in and filter content from other sections without any special configuration.

How it works

Every page summary in all_pages carries these fields:

FieldExampleDescription
title"Alice Müller"From frontmatter title:
url"/users/alice"Absolute URL of the page
slug"alice"Last path segment
section"/users"Parent path
extra{location: "lake-constance"}All other frontmatter fields
extra_lists{hosts: ["alice","bob"]}List-valued frontmatter fields
tags["guide","beginner"]Tag list
date"2026-06-15"Frontmatter date
snippet"A gentle paddle…"First ~200 chars of body

You filter all_pages in templates using Tera's built-in filter filter with attribute paths:

{% set guides = all_pages | filter(attribute="section", value="/users") %}
{% set here   = all_pages | filter(attribute="extra.location", value="lake-constance") %}

Tutorial: users, activities, and locations

This example builds a small site with three entity types that link to each other.

Content files

users/alice.md

---
title: Alice Müller
location: lake-constance
role: guide
---
Alice has been leading kayak tours since 2019 and knows every cove on the lake.

activities/morning-kayak.md

---
title: Morning Kayak Tour
location: lake-constance
host: alice
date: 2026-06-15
duration: 3h
level: beginner
---
A gentle paddle along the northern shore, suitable for all fitness levels.

locations/lake-constance.md

---
title: Lake Constance
region: southern-germany
---
Bordered by Germany, Austria, and Switzerland, Lake Constance offers calm
waters and dramatic Alpine views.

magic-circle.md — a standalone view page with no body:

---
title: The Magic Circle
layout: magic-circle
---

Layouts

Create these files under layouts/ in your site's git repository.

layouts/user-profile.html — resolves the user's location, lists their activities:

{% extends "base.html" %}
{% block main %}
<h1 class="title">{{ page.title }}</h1>
<p class="text-muted">{{ page.extra.role }}</p>

{{ page.content | safe }}

{% set location = all_pages | filter(attribute="slug", value=page.extra.location) | first %}
{% if location %}
<p>Based at <a href="{{ location.url }}">{{ location.title }}</a></p>
{% endif %}

{% set activities = all_pages | filter(attribute="section", value="/activities")
                               | filter(attribute="extra.host", value=page.slug) %}
{% if activities %}
<h2>Activities</h2>
{% for a in activities %}
<div class="mb-2">
  <a href="{{ a.url }}">{{ a.title }}</a>
  <span class="text-muted ms-2 small">{{ a.extra.date }} · {{ a.extra.level }}</span>
</div>
{% endfor %}
{% endif %}
{% endblock %}

layouts/activity.html — links back to its location and host:

{% extends "base.html" %}
{% block main %}
<h1 class="title">{{ page.title }}</h1>
<div class="text-muted mb-3">
  {{ page.extra.date }} · {{ page.extra.duration }} · {{ page.extra.level }}
</div>

{{ page.content | safe }}

{% set location = all_pages | filter(attribute="slug", value=page.extra.location) | first %}
{% set host     = all_pages | filter(attribute="slug", value=page.extra.host) | first %}

<div class="mt-3 d-flex gap-4">
  {% if location %}
  <span>Location: <a href="{{ location.url }}">{{ location.title }}</a></span>
  {% endif %}
  {% if host %}
  <span>Guide: <a href="{{ host.url }}">{{ host.title }}</a></span>
  {% endif %}
</div>
{% endblock %}

layouts/location.html — aggregates activities and guides for this location:

{% extends "base.html" %}
{% block main %}
<h1 class="title">{{ page.title }}</h1>
{{ page.content | safe }}

{% set activities = all_pages | filter(attribute="section", value="/activities")
                               | filter(attribute="extra.location", value=page.slug) %}
{% if activities %}
<h2>Activities here</h2>
{% for a in activities %}
<div class="mb-2">
  <a href="{{ a.url }}">{{ a.title }}</a>
  <span class="text-muted ms-2 small">{{ a.extra.date }} · {{ a.extra.level }}</span>
</div>
{% endfor %}
{% endif %}

{% set guides = all_pages | filter(attribute="section", value="/users")
                           | filter(attribute="extra.location", value=page.slug) %}
{% if guides %}
<h2>Guides based here</h2>
{% for u in guides %}
<div><a href="{{ u.url }}">{{ u.title }}</a></div>
{% endfor %}
{% endif %}
{% endblock %}

layouts/magic-circle.html — a free-form view that aggregates all three entity types:

{% extends "base.html" %}
{% block main %}
<h1 class="title">{{ page.title }}</h1>

<div class="row g-4">
  <div class="col-md-4">
    <h2>Locations</h2>
    {% for loc in all_pages | filter(attribute="section", value="/locations") %}
    <div class="card mb-2 p-2">
      <a href="{{ loc.url }}">{{ loc.title }}</a>
      {% set count = all_pages | filter(attribute="section", value="/activities")
                                | filter(attribute="extra.location", value=loc.slug) | length %}
      <small class="text-muted d-block">{{ count }} activit{{ count | pluralize(singular="y", plural="ies") }}</small>
    </div>
    {% endfor %}
  </div>

  <div class="col-md-4">
    <h2>Upcoming Activities</h2>
    {% for a in all_pages | filter(attribute="section", value="/activities") | sort(attribute="extra.date") %}
    <div class="mb-2">
      <a href="{{ a.url }}">{{ a.title }}</a><br>
      <small class="text-muted">{{ a.extra.date }} · {{ a.extra.level }}</small>
    </div>
    {% endfor %}
  </div>

  <div class="col-md-4">
    <h2>Guides</h2>
    {% for u in all_pages | filter(attribute="section", value="/users") %}
    <div class="mb-2">
      <a href="{{ u.url }}">{{ u.title }}</a>
      <small class="text-muted d-block">{{ u.extra.role }}</small>
    </div>
    {% endfor %}
  </div>
</div>
{% endblock %}

Wiring up the layouts

Each content file needs to reference its layout in frontmatter. Add layout: to the files that use a custom layout (the section _index.md is a good place for this):

users/_index.md

---
title: Guides
layout: list
---

users/alice.md — add layout: user-profile:

---
title: Alice Müller
layout: user-profile
location: lake-constance
role: guide
---

activities/morning-kayak.md — add layout: activity:

---
title: Morning Kayak Tour
layout: activity
location: lake-constance
host: alice
date: 2026-06-15
duration: 3h
level: beginner
---

locations/lake-constance.md — add layout: location:

---
title: Lake Constance
layout: location
region: southern-germany
---

Result

URLContent
/users/aliceAlice's bio + her location link + her activities
/activities/morning-kayakActivity details + location link + guide link
/locations/lake-constanceLocation description + all activities + all guides there
/magic-circleThree-column overview of all entities

Every link is resolved at render time by filtering all_pages — no foreign keys to declare, no joins to configure.

Filtering reference

GoalTemplate expression
All pages in a sectionall_pages | filter(attribute="section", value="/users")
Page with a specific slugall_pages | filter(attribute="slug", value="alice") | first
Pages matching a scalar fieldall_pages | filter(attribute="extra.location", value=page.slug)
Sort by a field… | sort(attribute="extra.date")
Count matches… | length
First match or nothing… | first (returns undefined if empty — guard with {% if … %})
site templates markdown