Skip to content

Configuration

The whole site is configured by a single config.toml at its root. This page documents every key.

How validation works

config.toml is strictly validated. An unknown key is an error, not a silent no-op — the build stops and names the offending key, with a "did you mean…?" suggestion when one is close. This is deliberate: a mistyped key that's quietly ignored is the worst way for a config to fail, especially one an agent edits.

The single exception is the [params] table, whose keys are intentionally free-form (see Custom values).

Top-level keys

title = "Demo Site"
base_url = "https://example.com"
Key Meaning
title The site name. Available to every template as site.title. Defaults to "Untitled Site".
base_url The site's public URL. Sets absolute links in sitemap.xml, and its path component becomes the prefix for internal links (see Deployment).

The remaining configuration lives in tables: [content_types.*], [taxonomies.*], [home], [nav], [profile], and [params].

Content types

A content type is a category of content with its own templates and URL scheme. Each maps to a folder under content/[content_types.blog] reads content/blog/*.md.

[content_types.blog]
template = "blog.html"
index_template = "blog.index.html"
permalink = "/blog/{slug}/"
index_permalink = "/blog/"
paginate = 10
sort_by = "date"
order = "desc"
Key Required Default Meaning
template yes Template for a single item of this type.
permalink yes URL pattern for a single item. See permalink tokens.
index_template no Template for the type's index (listing) page.
index_permalink no URL of the index page.
paginate no 0 Items per index page; 0 (or omitted) disables pagination. Must be a non-negative integer.
sort_by no "date" Front-matter field to sort the index by. Any field works, including a custom one.
order no "desc" "desc" (newest/largest first) or "asc".
feed no false Publish an RSS feed of this type's recent posts (see below).

index_template and index_permalink travel together: define both to get an index page, or neither for a type that has individual pages but no listing.

RSS feed

Set feed = true on a content type to publish an RSS 2.0 feed of its recent items at <index_permalink>feed.xml — e.g. a blog with index_permalink = "/blog/" gets /blog/feed.xml. It's a summary feed: each entry carries the post's title, link, date and description, not the body. The newest 20 items are included, newest first.

Two conditions gate it, both mirroring the sitemap: the feed's links are absolute, so it's only emitted when base_url is set; and it lives at the index URL, so the type must have an index (feed = true without one is a config error). Multiple types can each set feed = true for separate feeds. The starter base.html advertises every feed with a <link rel="alternate"> autodiscovery tag, driven by the site.feeds template variable — so feed readers and browsers find it automatically. The feed is regenerated only when a listed post's metadata changes (like the HTML listings) and never appears in sitemap.xml.

The pages type

pages is a reserved type for standalone pages — an about page, a colophon — that belong to no index and no taxonomy.

[content_types.pages]
template = "page.html"
permalink = "/{slug}/"

It takes only template and permalink. Declaring index_template or index_permalink on it is an error. Content in content/pages/ needs only a title and may not use taxonomies (see Authoring content).

Taxonomies

A taxonomy is a user-defined classification — tags, categories — applied by adding terms to a content file's front matter.

[taxonomies.tags]
template = "taxonomy.html"
index_template = "taxonomy.index.html"
permalink = "/tags/{term}/"
index_permalink = "/tags/"
multiple = true
sort_by = "count"
order = "desc"
home = true

[taxonomies.tags.items]   # how items are ordered on a term page
sort_by = "date"
order = "desc"
Key Required Default Meaning
template yes Template for a single term's page (the items tagged with it).
permalink yes URL pattern for a term page; use the {term} token.
index_template no Template for the taxonomy index (all terms).
index_permalink no URL of the taxonomy index.
multiple no true Front-matter shape: true expects a list (tags = ["a", "b"]); false expects a single string (category = "AI").
sort_by no "name" Term ordering (the index page and home cloud): "name" (alphabetical) or "count" (most-used first).
order no "asc" "asc" or "desc". Applies to the term sort_by.
home no false When true, the home template receives this taxonomy's terms as taxonomies.<name>.

Item order on a term page

sort_by/order above order the terms. To order the items shown on a single term page (e.g. /tags/python/), use the nested [taxonomies.<name>.items] sub-table:

Key Required Default Meaning
sort_by no "date" Any front-matter field, exactly like a content type's sort_by — a custom field works too. A field present on none of the taxonomy's items fails the build.
order no "desc" "asc" or "desc".

Omit the sub-table and items default to newest-first (date desc), matching a type index. Because a term can span content types, this one ordering applies to all of a term's items regardless of type.

Home

The landing page.

[home]
template = "home.html"
recent = { blog = 5, project = 3 }
Key Meaning
template Required. The landing-page template.
recent A content-type = count table. The template receives each as recent.<type> — the newest count items of that type.

Every content type recent references must exist.

The site nav bar. labels and links are two arrays paired by position, so they must be the same length.

[nav]
enabled = true
labels = ["Blog", "Projects", "Tags", "About"]
links  = ["/blog/", "/projects/", "/tags/", "/about/"]

Templates read the paired result as site.nav, a list of items with .label and .link. Set enabled = false to hide the nav without deleting its entries.

Profile

Author/owner details, exposed to every template as site.profile.

[profile]
name = "Demo User"
bio = "A line or two about who you are."
avatar = "/img/avatar.svg"
email = "you@example.com"
socials = { github = "https://github.com/you", mastodon = "https://mastodon.social/@you" }

avatar is a path under static/. socials maps a platform key to its URL and keeps its written order, so links render in order and the key is available for icon or label lookup. Every field is optional.

Custom values ([params])

[params] is the one table whose keys are not validated — the escape hatch for arbitrary site-wide values.

[params]
accent       = "teal"
show_sidebar = true
analytics_id = "UA-123"

Read them in any template as site.params.<key>, e.g. {{ site.params.accent }} or {% if site.params.show_sidebar %}. For per-page custom values, use front matter and page.params instead — see Custom fields.

The raw parsed config is also available to templates as site.config, if a template needs a value no dedicated variable exposes.