MADORIMADORI

Taxonomies

Taxonomies let you categorise and tag content. Tags, categories, topics, genres — any way you want to group entries across collections. Each taxonomy contains terms that can be assigned to collection entries via the taxonomy field type.

Taxonomies are defined as flat files, managed visually in the Control Panel, and queryable via REST and GraphQL APIs.


Configuration Reference

Taxonomy Definition

Taxonomy definitions live at resources/taxonomies/{handle}.yaml. The handle is the taxonomy's identifier used in collection associations and API endpoints.

Property Type Required Default Description
title string Yes Display name shown in the Control Panel sidebar
blueprint string No Handle of a blueprint for term fields (optional)

Example definition:

# resources/taxonomies/tags.yaml
title: Tags
blueprint: tags

Term Storage

Terms are stored as YAML files at content/taxonomies/{taxonomy}/{slug}.yaml:

# content/taxonomies/tags/javascript.yaml
title: JavaScript
slug: javascript
description: Posts about the JavaScript language

Term Properties

Property Type Required Description
title string Yes Display name for the term
slug string Yes URL-safe identifier (matches filename)
Additional fields varies No Defined by the taxonomy's blueprint

Blueprint Fields for Terms

When a taxonomy references a blueprint, terms gain additional fields beyond title and slug:

# resources/blueprints/taxonomies/tags.yaml
tabs:
  main:
    fields:
      - handle: description
        field:
          type: text
          display: Description
          validate:
            - max:200

      - handle: color
        field:
          type: text
          display: Color
          options:
            placeholder: "#3b82f6"

Collection Association

Associate taxonomies with collections via the taxonomies array in collection definitions:

# resources/collections/blog.yaml
title: Blog
blueprint: blog
taxonomies:
  - tags
  - categories

API Endpoints

Method Endpoint Description
GET /api/taxonomies List all taxonomy definitions
GET /api/taxonomies/{handle}/terms List all terms for a taxonomy
GET /api/taxonomies/{handle}/terms/{slug} Get a single term
POST /api/taxonomies/{handle}/terms Create a term
PUT /api/taxonomies/{handle}/terms/{slug} Update a term
DELETE /api/taxonomies/{handle}/terms/{slug} Delete a term

File Structure

resources/
├── taxonomies/
│   ├── tags.yaml              # Definition
│   └── categories.yaml        # Definition
├── blueprints/taxonomies/
│   ├── tags.yaml              # Blueprint (optional)
│   └── categories.yaml        # Blueprint (optional)
content/
└── taxonomies/
    ├── tags/
    │   ├── javascript.yaml    # Term
    │   ├── typescript.yaml    # Term
    │   └── react.yaml         # Term
    └── categories/
        ├── tutorials.yaml     # Term
        └── news.yaml          # Term

Usage Examples

Creating a Taxonomy

Step 1: Create the definition:

# resources/taxonomies/categories.yaml
title: Categories
blueprint: categories

Step 2: (Optional) Create a blueprint for term fields:

# resources/blueprints/taxonomies/categories.yaml
tabs:
  main:
    fields:
      - handle: description
        field:
          type: text
          display: Description

      - handle: icon
        field:
          type: text
          display: Icon Name
          options:
            placeholder: e.g. book, code, globe

Step 3: Create terms via the Control Panel or as files.

Creating Terms via the Control Panel

  1. Navigate to Taxonomies in the sidebar
  2. Click the taxonomy (e.g. "Tags")
  3. Click Create Term
  4. Enter a title (slug auto-generates)
  5. Fill any additional blueprint fields
  6. Save

Creating Terms via Files

# content/taxonomies/tags/nextjs.yaml
title: Next.js
slug: nextjs
description: Content related to the Next.js framework
color: "#000000"

Using Taxonomy Fields in Blueprints

Add a taxonomy field to your collection blueprint:

- handle: tags
  field:
    type: taxonomy
    display: Tags

- handle: categories
  field:
    type: taxonomy
    display: Categories
    required: true
    validate:
      - required

Editors select terms from the associated taxonomy when creating or editing entries.

Querying Terms via GraphQL

{
  terms(taxonomy: "tags") {
    title
    slug
  }
}

Querying Terms via REST API

# List all terms
curl http://localhost:3000/api/taxonomies/tags/terms

# Get single term
curl http://localhost:3000/api/taxonomies/tags/terms/javascript

Common Patterns

Tags vs Categories

Use two taxonomies for different grouping strategies:

# resources/taxonomies/categories.yaml
title: Categories
# Broad, exclusive grouping (an entry typically has one category)

# resources/taxonomies/tags.yaml
title: Tags
# Narrow, inclusive labelling (an entry can have many tags)

Hierarchical Categories

While Madori taxonomies are flat (terms don't nest), you can simulate hierarchy with naming conventions:

# content/taxonomies/categories/
frontend.yaml          # title: Frontend
frontend-react.yaml    # title: Frontend > React
frontend-vue.yaml      # title: Frontend > Vue
backend.yaml           # title: Backend
backend-node.yaml      # title: Backend > Node.js

Filtering Entries by Taxonomy

Query entries that have specific taxonomy terms assigned:

{
  blogs(filter: { tags: "javascript" }) {
    title
    slug
  }
}

Taxonomy Landing Pages

Build pages that list all entries for a specific term:

// app/tags/[slug]/page.tsx
export default async function TagPage({ params }) {
  const { slug } = params

  const data = await queryGraphQL(`
    query GetTaggedPosts($tag: String!) {
      blogs(filter: { tags: $tag, status: "published" }) {
        title
        slug
        createdAt
      }
    }
  `, { tag: slug })

  return (
    <div>
      <h1>Posts tagged: {slug}</h1>
      <ul>
        {data.blogs.map(post => (
          <li key={post.slug}>
            <a href={`/blog/${post.slug}`}>{post.title}</a>
          </li>
        ))}
      </ul>
    </div>
  )
}

Displaying Term Metadata

If your taxonomy has a blueprint with additional fields, use the terms API to fetch metadata:

async function getTagWithMeta(slug: string) {
  const res = await fetch(`/api/taxonomies/tags/terms/${slug}`)
  return res.json()
}

// Returns: { title: "JavaScript", slug: "javascript", description: "...", color: "#f7df1e" }

Multi-Taxonomy Filtering

Associate multiple taxonomies with a collection for flexible content organisation:

# resources/collections/blog.yaml
title: Blog
blueprint: blog
taxonomies:
  - categories    # Broad grouping
  - tags          # Detailed labels
  - authors       # Content by author