Standard tag pages list content for one tag (e.g.,/tags/python/). But sometimes users want to find content that matches multiple criteria, like "Tutorials" AND "Python" AND "Beginner".
This guide shows how to build an advanced filter using Kida template set logic.
The Logic: Set Intersections
Kida (and Jinja2) allows us to treat lists of pages as mathematical sets.
- Union: All unique items in A or B.
- Intersection: Items that are in BOTH A and B.
- Difference: Items in A but not in B.
Example: Building a "Recipe Finder"
Imagine a documentation site where you want to find "API Guides" for "v2.0".
1. Accessing the Data
Bengal exposessite.taxonomieswhich gives us lists of pages for each tag.
{% let api_pages = site.taxonomies.tags["api"].pages %}
{% let v2_pages = site.taxonomies.tags["v2"].pages %}
2. Finding the Intersection
Use the|> intersect()filter to find pages in both lists:
{% let results = api_pages |> intersect(v2_pages) %}
<h2>API v2 Guides ({{ results | length }})</h2>
<ul>
{% for page in results %}
<li><a href="{{ page.href }}">{{ page.title }}</a></li>
{% end %}
</ul>
Tip
For more complex filtering, use|> where()with operators:
{% let results = site.pages
|> where('tags', 'api', 'in')
|> where('tags', 'v2', 'in') %}
Advanced: The "Filter Page" Layout
For a dynamic filter page (e.g.,/search/), we typically rely on client-side JavaScript because pre-rendering every combination of tags is expensive (combinatorial explosion).
However, for specific, high-value combinations, you can create dedicated pages.
Step 1: Create the Page
site/content/guides/python-tutorials.md:
---
title: Python Tutorials
variant: filter_page
filter_tags: ["python", "tutorial"]
---
Here are all our Python tutorials.
Step 2: Create the Layout
templates/filter_page.html:
{% extends "base.html" %}
{% block content %}
<h1>{{ page.title }}</h1>
{# Start with all pages, then filter by each required tag #}
{% let matches = site.pages %}
{% for tag in page.metadata.filter_tags %}
{% let tag_pages = site.pages |> where('tags', tag, 'in') %}
{% let matches = matches |> intersect(tag_pages) %}
{% end %}
{# Render Results #}
<div class="results">
{% for post in matches %}
{% include "partials/card.html" %}
{% else %}
<p>No matches found.</p>
{% end %}
</div>
{% end %}
Summary
Use Set Intersections to build powerful "Topic Pages" that aggregate content from multiple dimensions without manually curating lists.
Seealso
- Filter by Multiple Tags — Complete cookbook recipe
- Content Reuse — DRY content strategies
- Templating — Template fundamentals