Taxonomies
Classify content with tags, categories or your own taxonomies, and list terms and their pages.
A taxonomy groups pages by terms: the taxonomy tags with the terms rust and web. fugo creates a page for each taxonomy (/tags/) and each term (/tags/rust/).
Configure taxonomies#
The default taxonomies are tags and categories. Define your own, singular name first:
[taxonomies]
tag = "tags"
category = "categories"
series = "series"taxonomies:
category: categories
series: series
tag: tags{
"taxonomies": {
"category": "categories",
"series": "series",
"tag": "tags"
}
}Defining [taxonomies] replaces the defaults; an empty table, or disableKinds = ["taxonomy", "term"], turns taxonomies off.
Assign terms#
+++
title = "Hello"
tags = ["rust", "web"]
series = ["Getting started"]
+++---
series:
- Getting started
tags:
- rust
- web
title: Hello
---{
"series": [
"Getting started"
],
"tags": [
"rust",
"web"
],
"title": "Hello"
}A term’s key is its name made URL-safe: Getting started is /series/getting-started/. A page’s position in a term’s list can be set with a weight: tags_weight = 10.
Templates#
A taxonomy page uses taxonomy.html, a term page term.html (both fall back to list.html). On a taxonomy page, page.taxonomy has the terms:
<h1>{{ page.title }}</h1>
<ul>
{% for t in page.taxonomy.terms | by_count %}
<li><a href="{{ t.page.rel_permalink }}">{{ t.name }}</a> ({{ t.count }})</li>
{% endfor %}
</ul>A term page lists its pages as any list page does: page.pages, page.term.name.
A page’s terms, e.g. in single.html:
{% for t in page.terms.tags %}
<a href="{{ t.rel_permalink }}">#{{ t.title }}</a>
{% endfor %}Every term of a taxonomy, anywhere: site.taxonomies.tags maps each term’s key to its name, page, count and pages.
Term pages with content#
Add content/tags/rust/_index.md to give a term page a title, a description and content.
Hierarchical taxonomies#
Terms can form a tree, such as product types or places. Turn it on per taxonomy with the table form of [taxonomies]:
[taxonomies]
tag = "tags"
[taxonomies.category]
plural = "categories"
hierarchical = truetaxonomies:
category:
hierarchical: true
plural: categories
tag: tags{
"taxonomies": {
"category": {
"hierarchical": true,
"plural": "categories"
},
"tag": "tags"
}
}A / in a term nests it: categories = ["snacks/chips"] is the term /categories/snacks/chips/ below /categories/snacks/. In a hierarchical taxonomy:
- Every term above a term exists: fugo makes the missing term pages, titled with their segment as written (
snacks,Snacksonce titled). - A term lists its own pages and those of every term below it, each page once (
page.pages, and the term’scountandpages). The smallest weight of a page counts. - The taxonomy page lists the top-level terms.
page.sectionsof the taxonomy page and of a term page are the terms directly below it, andpage.parentandpage.ancestorsfollow the tree, so breadcrumbs need no change. - A term without a
/that is not a top-level term names the one term that ends in it. Oncecontent/categories/snacks/chips/_index.mdexists, or a page writessnacks/chips,categories = ["chips"]meanssnacks/chips. When several terms end in it, fugo warns (taxonomy-ambiguous-term) and keeps the value top-level: write the term’s path. - A page’s own terms (
page.terms) are the ones it names; term keys (page.term.key, the keys ofsite.taxonomies.categories) are paths below the taxonomy:snacks/chips.
Declare the tree once with term pages, and let pages name the last term only:
content/categories/snacks/_index.md
content/categories/snacks/chips/_index.md
content/posts/lays.md categories = ["chips"]Term URLs follow the tree (/categories/snacks/chips/). To keep them flat, so that moving a term in the tree does not change its URL, give terms a permalink made of the last segment of their key:
[permalinks.term]
categories = "/categories/:sections[last]/"permalinks:
term:
categories: /categories/:sections[last]/{
"permalinks": {
"term": {
"categories": "/categories/:sections[last]/"
}
}
}The tree still drives parent, ancestors and sections. This keeps the URLs of a flat taxonomy as they were when it becomes hierarchical (:slug would make them again from the title: Cheddar & Sour Cream is cheddar--sour-cream as a key but cheddar-sour-cream as a slug). When a term’s URL changes, keep the old one working with aliases in its _index.md.
With flat URLs, terms in different places of the tree may not end in the same segment: news/sport and blog/sport would both be /categories/sport/, and the build fails (taxonomy-term-collision). Rename one of them, or give it a url in its _index.md.
Pages can follow their terms too: :term[categories] in a page’s permalink is the first category the page names, by its last segment. With flat term URLs, each page then sits below its category’s page:
[permalinks.term]
categories = "/:sections[last]/"
[permalinks.page]
posts = "/:term[categories]/:slugorfilename/"permalinks:
page:
posts: /:term[categories]/:slugorfilename/
term:
categories: /:sections[last]/{
"permalinks": {
"page": {
"posts": "/:term[categories]/:slugorfilename/"
},
"term": {
"categories": "/:sections[last]/"
}
}
}content/posts/hello/index.md with categories = ["rust"] is /rust/hello/, below /rust/, and its folder says nothing about its category. Its URL changes when its first category does: keep the old one working with aliases.