Configuring the site

One trail.toml at the site root configures the whole site. It is the only place these settings live — there is no per-environment config, no CLI equivalent for most of them, and unknown keys are build errors rather than typos you find out about later.

sitename = "Peios Learn"
title = "Documentation for everything Peios"
url = "https://learn.peios.org"
accent = "#3b82f6"
description = "Concepts, guides, and reference for the Peios operating system and every project around it — from the kernel to the toolchain that builds it."

featured = ["peios", "pekit", "provium", "universal-directory", "trail"]

footer = "Peios Learn — documentation for the Peios project."

The trail.toml reference is the exhaustive table; this page is what each setting is for.

The four required keys #

sitename, title, description and footer must all be present.

sitename is the site's identity: the wordmark in the header, the suffix on every page's <title>, the search box's placeholder, and og:site_name. Its last word is accented in the wordmark — "Peios Learn" — so a two-word name reads best. A one-word name simply gets no accent.

title and description are the front page's headline and standfirst, and its meta description and social-preview text. The description is also the first line of llms.txt, so write it as a summary of the whole site rather than a slogan.

footer is the line at the foot of every page. Beneath it, "Built with Trail." appears unless built_by_trail = false turns it off.

The base URL #

url = "https://learn.peios.org"

Optional, and worth setting before you deploy. Without it:

  • no sitemap.xml is written, because sitemaps require absolute URLs, and robots.txt gets no Sitemap: line;
  • canonical URLs stay root-relative rather than absolute;
  • og:url is omitted, since a relative one is meaningless to the crawlers reading it;
  • /print bundles link outward relatively, which is right on the site and wrong on paper.

Trailing slashes are trimmed, so https://learn.peios.org/ and https://learn.peios.org behave identically.

featured = ["peios", "pekit", "provium", "universal-directory", "trail"]

The list does two jobs: it orders products, and it decides which appear on the front page.

  • Products in the list sort first, in the list's order; everything else follows, by title.
  • Only listed products get a card on the front page. An unlisted product is still built, still searchable, still linkable, and still in the header's products menu.
  • Naming a product that does not exist is a build error.

Header navigation #

[[nav]]
label = "Specs"
url = "~peios/pgss"

[[nav]]
label = "Source"
url = "https://github.com/peios/peios"

Each [[nav]] block adds a link to the header, beside the products menu. On narrow screens they move inside that menu.

Keep the [[nav]] blocks at the end of the file: in TOML every key after a table header belongs to that table, so an ordinary key written below them becomes a nav field and fails the build.

url may be an external URL, a root-relative path, or a ~ page reference. References are resolved strictly, at load time — even with --allow-dangling-links, a broken nav link fails the build. Site chrome appears on every page; it must never dangle.

Favicon #

favicon = "favicon.png"

A path relative to the site root. The file is copied to the output root under its own name and linked from every page. The file must exist, or the build fails.

Naming a file here is also what makes it legal to keep in the site root, which otherwise accepts only trail.toml and *.product directories.

edit_url = "https://github.com/peios/learn/edit/main/{path}"

Adds an "Edit this page" link to the foot of every article. {path} is replaced with the article's source file path relative to the site root — the placeholder is required, and a template without it is a build error.

For an alias page the link points at the original's source file, since that is the file to edit.

Injecting your own head HTML #

head_html = "head.html"

A path to a file whose contents are injected verbatim at the end of every page's <head>: analytics snippets, extra meta tags, a webfont, a verification token.

It is inserted unescaped and unchecked, at the end of the head, so it can override earlier tags. It is the escape hatch for everything trail does not have a setting for — and, like all escape hatches, the thing to reach for last.

Files trail does not build #

passthrough = ["CNAME", ".well-known"]

Some files have to be in the published site without trail having any opinion about them: a CNAME for a custom domain, a .well-known/ directory, a search-engine verification file. passthrough names them, and each one is copied into the output exactly as it is — directories whole.

This matters most when the site root is a repository root. Trail accepts only trail.toml and *.product directories there, so a CNAME sitting beside them would otherwise fail the build. Naming it here makes it legal and publishes it.

Two details worth knowing:

  • Entries are copied after everything trail generates, so naming robots.txt replaces the generated one — useful, and a foot-gun if you name assets.
  • Dot-entries like .github/ are already skipped by the root scan, so they only need naming here if you want them published. .well-known/ does; .github/ does not.

Theming #

Four keys control colour:

accent = "#3b82f6"
accent_dark = "#7aa8ff"     # optional; derived from accent if absent
custom_css = "custom.css"   # optional
product_theming = true      # default

accent is the site's colour. accent_dark overrides its dark-mode variant, which is otherwise derived by mixing the accent toward white. custom_css names a stylesheet shipped at /assets/custom.css and loaded after the built-in one. product_theming = false stops each product tinting its own pages.

Both colours must be #rrggbb, and setting accent_dark without accent is an error. Theming covers what these actually reach.

What may live in the site root #

The site root accepts trail.toml, *.product directories, the build output directory, dot-entries (.git and friends), and whatever favicon, custom_css, head_html and passthrough name. A setting naming assets/site.css makes the whole assets/ directory legal at the root — it is the first path component that is tolerated. Anything else is a build error.

That last clause is the reason those three settings take paths rather than inline content: naming a file is what makes it part of the site.

Edit this page