Complete specification for TOML frontmatter in Zorto content files. Frontmatter is enclosed in +++ delimiters at the top of every .md file.

+++
title = "My page"
date = "2026-01-15"
+++

If no +++ block is present, Zorto uses default values for all fields.

Page frontmatter #

Used in regular .md files (anything that is not _index.md).

FieldTypeDefaultDescription
titlestring""Page title, used in templates and feeds
datestring or datetimenonePublication date (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS). Pages without dates sort last in date-ordered sections
authorstringnoneAuthor name
descriptionstringnoneShort summary for SEO, feeds, and llms.txt
draftboolfalseIf true, excluded from production builds
slugstringfilenameOverride the URL slug. By default, derived from the filename (e.g. my-post.md becomes my-post)
templatestring"page.html"Custom template for this page
weightintnoneSort weight for ordering within a section (lower values first). Used with sort_by = "weight"
aliasesarray of strings[]Additional URL paths that redirect to this page
[extra]table{}Arbitrary key-value data, accessible in templates as page.extra
taxonomy fieldsarray of strings[]Top-level arrays are interpreted as taxonomy values (e.g. tags = ["rust"])

Computed fields #

These fields are not set in frontmatter but are available in templates:

FieldTypeDescription
page.pathstringURL path relative to site root (e.g. "/posts/hello/")
page.permalinkstringFull URL including base_url
page.contentstringRendered HTML content
page.summarystring or nullHTML content before <!-- more --> marker
page.raw_contentstringRaw markdown after frontmatter extraction
page.taxonomiesobjectTaxonomy values keyed by name (e.g. {"tags": ["rust", "web"]})
page.word_countintApproximate word count
page.reading_timeintEstimated reading time in minutes (word_count / 200, minimum 1)
page.relative_pathstringSource file path relative to content directory

Section frontmatter #

Used in _index.md files that define sections (directories).

FieldTypeDefaultDescription
titlestring""Section title
descriptionstringnoneSection description
sort_bystringnoneSort pages: "date" (reverse chronological), "title" (alphabetical), or "weight" (ascending by weight, filename tiebreak)
paginate_byintnonePages per pagination page. Omit or set to 0 to disable pagination
render_pagesbooltrueWhen false, child pages are not rendered as individual HTML files. Their content is still available in section.pages for use in templates. Used for presentations
templatestring"section.html"Custom template for this section
[extra]table{}Arbitrary key-value data, accessible in templates as section.extra

Computed fields #

FieldTypeDescription
section.pathstringURL path relative to site root (e.g. "/posts/")
section.permalinkstringFull URL including base_url
section.contentstringRendered HTML from the _index.md body
section.raw_contentstringRaw markdown after frontmatter extraction
section.pagesarrayPages belonging to this section, sorted per sort_by
section.relative_pathstringSource file path relative to content directory

Taxonomy values #

Taxonomy values are defined as top-level arrays in page frontmatter. Any top-level key whose value is an array of strings is treated as a taxonomy assignment:

+++
title = "Building a web app"
tags = ["rust", "web", "tutorial"]
categories = ["engineering"]
+++

The taxonomy names must match those defined in config.toml under [[taxonomies]]. See taxonomies in depth for the full workflow.

Slug derivation #

The URL slug determines the page’s URL path. Zorto derives it in this order:

  1. Explicit slug field in frontmatter, if set
  2. Directory name for co-located content (posts/my-post/index.md uses slug my-post)
  3. Filename for regular files (my-post.md uses slug my-post)

Slugs are always lowercased and URL-safe (spaces become hyphens, special characters are removed).

Co-located content #

Pages can use directory-based organization for co-located assets:

📂content/posts/
├── 📂my-post/
    ├── 📝index.mdpage -> /posts/my-post/
    ├── 📝photo.jpg
    ├── 📝diagram.svg

Co-located content uses index.md inside a named directory.

The index.md file becomes the page content, and sibling files are copied as assets. Reference them with relative paths in your markdown.

Date formats #

The date field accepts:

  • Date string: "2026-01-15"
  • Datetime string: "2026-01-15T10:30:00"
  • TOML datetime: 2026-01-15T10:30:00 (unquoted)

All formats are normalized to a string for template rendering.

Examples #

Minimal page #

+++
title = "About"
+++

Full page #

+++
title = "Building a static site generator"
date = "2026-03-15"
author = "Cody"
description = "How and why I built Zorto."
draft = false
slug = "building-zorto"
template = "post.html"
aliases = ["/blog/old-url/"]
tags = ["rust", "ssg"]
categories = ["engineering"]

[extra]
featured = true
hero_image = "/images/zorto-hero.png"
+++

Section with pagination #

+++
title = "Blog"
description = "Posts about engineering and design."
sort_by = "date"
paginate_by = 10
template = "blog.html"

[extra]
show_sidebar = true
+++

Further reading #