# Structuring a site

---

# Products

_Trail / Structuring a site_

> A product is the top-level division of a trail site — a documented thing with its own landing page, colour, monogram and URL prefix. What goes in one, what its trail.toml needs, and how products are ordered.

A **product** is the outermost division of a trail site: one documented thing, with its own landing page, its own colour, and its own URL prefix. Products are the only children the site root will accept, so every page in the site belongs to exactly one.

On this site, `pekit`, `provium` and `trail` are products. So is `peios` itself — products are not necessarily software packages, they are simply the largest chunk of documentation a reader would think of as one subject.

## The directory

A product is a directory named `<slug>.product` at the site root. It has no order prefix.

```text
learn/
├── trail.toml
├── pekit.product/          →  /pekit
└── trail.product/          →  /trail
```

The slug becomes the URL prefix (`/pekit`) and the first segment of every [`~link`](/trail/writing/links-and-references.md) into that product. It must be lowercase kebab-case, and it may not be `assets` or `pagefind` — those collide with the output directories trail writes.

## The config

Every product needs a `trail.toml`, and all four keys are required:

```toml
# pekit.product/trail.toml
title = "pekit"
monogram = "pk"
color = "#22c55e"

description = "The recipe-driven build and packaging tool — declarative recipes in; built, tested, packaged software out."
```

| Key | |
|---|---|
| `title` | The product's display name, used everywhere the product is named. Unlike other containers, this is not derived from the slug — a product always states it. |
| `monogram` | A very short string — usually two characters — shown on the product's tile, on the front-page card and at the top of the product page. Initials or a shortened name. |
| `color` | A `#rrggbb` hex colour. Any other form is a build error. |
| `description` | One sentence, shown on the front-page card, under the product's name on its own page, and in `llms.txt`. It is also the product page's meta description. |

One optional key, `inline_ref`, claims phrases that auto-link to the product page wherever they appear in prose; see [Inline references](/trail/writing/inline-references.md).

## What the colour does

`color` is the product's accent, and by default it displaces the site accent on every page belonging to that product: card borders and hover states, the tile, sidebar highlights, heading numbers, RFC-2119 keywords, focus rings.

Setting `product_theming = false` in the root `trail.toml` turns this off site-wide, and everything tints from the site accent instead. Products still keep their monogram and card, they just stop colouring their pages. See [Theming](/trail/building/theming.md).

## What a product contains

A product directory holds its `trail.toml` and nothing but grouping directories:

- [**Anthologies**](/trail/structuring-a-site/anthologies-and-shelves.md) (`.antho`) — a titled landing page with its own children, for products big enough to need a second level.
- [**Topics**](/trail/structuring-a-site/topics-and-folders.md) (`.topic`) — a set of articles read in any order. The everyday container.
- [**Books**](/trail/structuring-a-site/books.md) (`.book`) — a formal, ordered document with a cover page, numbered sections and appendices.
- [**Shelves**](/trail/structuring-a-site/anthologies-and-shelves.md) (`.shelf`) — a titled heading grouping some of the above on the product page. No URL segment of its own.

Articles, images and `.link` files may **not** sit directly in a product directory; they live inside topics and books. A product with nothing in it is legal and simply renders an empty landing page.

Small products go straight to topics:

```text
pekit.product/
├── trail.toml
├── 1--getting-started.topic/
├── 2--recipes.topic/
├── 3--running.topic/
└── 4--reference.topic/
```

Large ones add a layer:

```text
peios.product/
├── trail.toml
├── 1--security-fundamentals.antho/
├── 2--using-peios.antho/
├── 3--advanced-peios.antho/
├── 4--developing-for-peios.antho/
└── 5--peiso.antho/
```

Both shapes are ordinary. Reach for an anthology when a product's topic list has grown long enough that readers have to hunt through it.

## The product page

Every product gets a landing page at `/<slug>`, built from the config and its children:

- A hero with the monogram tile, the title and the description.
- A "Documentation" section listing every child as a card. Anthologies and books get a card with their description; topics get a card listing their articles — all of them when there are four or fewer, otherwise the first three and a "See all N articles" link — with a count and the topic's total reading time.
- Each shelf becomes a subheading above its own row of cards. Runs of items outside any shelf render as an untitled row, in place.

## Ordering

Products have no order prefix. They sort by the root `trail.toml`'s `featured` list — in that list's order — and then everything not listed, by title.

```toml
# learn/trail.toml
featured = ["peios", "pekit", "provium", "universal-directory", "trail"]
```

That list does more than sort. **The front page shows only featured products.** An unfeatured product is still built, still searchable, still linkable, and still in the header's products menu — it just does not get a card on the front page. Naming a product that does not exist in `featured` is a build error.

## Roll-ups

A product totals up what is beneath it. Its reading time is the sum of every article's, and its `updated` date is the most recent `updated:` in the whole product. Anthologies, topics, books and chapters do the same at their own level. See [Articles and frontmatter](/trail/writing/articles-and-frontmatter.md).

## When to add a product

A product is a heavy division: its own colour, its own landing page, its own URL prefix, and a separate card on the front page. Add one when readers would go looking for the subject by name and would not expect to find it filed under something else.

Within a single product, the lighter divisions — anthologies for a second level of landing pages, shelves for a heading, topics for a set of articles — are almost always the better answer.

---

# Anthologies and shelves

_Trail / Structuring a site_

> Two ways to group a product's contents — an anthology is a second landing page with its own URL, a shelf is a heading on the page above it. When to reach for each, and how deep they nest.

Once a product has more than a handful of topics, its landing page becomes a wall of cards. Trail offers two ways to break that up, and the difference between them is exactly one thing: **whether the grouping gets a page of its own**.

| | URL segment | Page | Sidebar | Nests |
|---|---|---|---|---|
| **Anthology** (`.antho`) | yes | its own landing page | — | in products and anthologies |
| **Shelf** (`.shelf`) | no | no — a heading on its parent's page | — | in products and anthologies, never in a shelf |

Reach for a shelf when the topics belong together but readers should still see them all at once. Reach for an anthology when the group is big enough to deserve its own front door.

## Anthologies

An anthology is a directory named `<order>--<slug>.antho`. It has a landing page at its own URL, listing everything inside it exactly as a product page lists its own children.

```text
peios.product/
├── trail.toml
├── 1--security-fundamentals.antho/     →  /peios/security-fundamentals
│   ├── trail.toml
│   ├── 1--identity.topic/              →  /peios/security-fundamentals/identity
│   └── 2--pgss.book/                   →  /peios/security-fundamentals/pgss
└── 2--using-peios.antho/               →  /peios/using-peios
```

Its `trail.toml` requires two keys:

```toml
# 1--security-fundamentals.antho/trail.toml
title = "Security fundamentals"
description = "How Peios decides who may do what: identity, tokens, and the two gates every request passes."
```

`title` is the heading and the breadcrumb; `description` is the standfirst on the page, the text on the card that links to it from the product page, and the entry in `llms.txt`. The optional `inline_ref` key claims phrases pointing at this anthology's page; see [Inline references](/trail/writing/inline-references.md).

An anthology may contain anthologies, topics, books and shelves — the same set a product may contain. Anthologies nesting inside anthologies is legal and unbounded, and each level adds a URL segment:

```text
/peios/developing-for-peios/apis/filesystem/open
      └─ anthology ──────┘ └ antho ┘ └ topic ─┘ └ article
```

In practice two levels is plenty. Deeper than that and readers stop being able to guess where anything lives.

### The anthology page

The page mirrors a product page one level down: a breadcrumb trail back to the product (and through any parent anthologies), the title, the description, and a "Topics" section of cards. Nested anthologies and books get a description card; topics get a card listing their articles.

## Shelves

A shelf is a directory named `<order>--<slug>.shelf`. It is presentation only: **a shelf contributes no URL segment, has no page, and never appears in a breadcrumb.** Its whole job is to put a subheading above a row of cards on the page it sits in.

```text
peios.product/
└── 3--tooling.shelf/            (no URL of its own)
    ├── trail.toml
    ├── 1--pekit.topic/          →  /peios/pekit
    └── 2--provium.topic/        →  /peios/provium
```

Note the URLs: the topics live directly under the product, exactly as they would if the shelf directory were not there.

Its `trail.toml` is optional and carries at most a title:

```toml
# 3--tooling.shelf/trail.toml
title = "Tooling"
```

Without one, the title is derived from the slug — `3--tooling.shelf` becomes "Tooling" anyway, so most shelves need no config at all. A shelf may **not** declare `inline_ref`: it has no page to link to, so the phrase would have nowhere to land. Declare it on the shelf's items instead.

### How shelves render

On the parent's page, children render in order. A run of items outside any shelf renders as an untitled row of cards; each shelf renders as its title followed by its own row:

```text
Documentation

  [ Getting started ]  [ Concepts ]          ← loose items, no heading

  Tooling                                    ← shelf title
  [ pekit ]  [ provium ]

  Specifications                             ← another shelf
  [ PGSS ]  [ PCDS ]
```

Because a shelf's items share their parent's URL space, their slugs must be unique across the whole parent — two shelves cannot both contain a `getting-started` topic, since both would want `/peios/getting-started`. Trail rejects that at build time.

### The rules

- A shelf may sit in a product or an anthology.
- A shelf may contain anthologies, topics and books.
- **A shelf may never contain another shelf.** Nested headings on a card grid are not a structure worth having; if you need the second level, use an anthology.
- A shelf directory holds `trail.toml` and subdirectories only — no articles, no images.

## Choosing

Start flat. A product with four or five topics needs neither of these.

When the list gets long, ask whether the groups are worth a page. "Tooling" as a heading over two topic cards is a shelf. "Security fundamentals" — nine topics, two specifications, and a description worth reading — is an anthology.

The cost of an anthology is a URL segment on every page beneath it and one more click for the reader. The cost of a shelf is nothing at all, which is why it is usually the right first move.

---

# Topics and folders

_Trail / Structuring a site_

> The topic is trail's everyday container — a set of articles read in any order, with an optional single level of subfolders. Where the sidebar comes from, why a topic has no page, and where links to one land.

A **topic** is a set of articles on one subject, read in any order. It is the container most pages live in, and the one to reach for unless you specifically need a [book](/trail/structuring-a-site/books.md).

"Getting started", "Concepts", "Configuration", "Reference" — those are topics. The reader arrives at one of the articles from search or a link, reads it, and moves on; the sidebar is there for when they want to see what else is nearby.

## The directory

A topic is a directory named `<order>--<slug>.topic`, sitting in a product, an anthology or a shelf. Its articles are the `.md` files inside it:

```text
4--reference.topic/                 (the topic; no page of its own)
├── trail.toml                      optional
├── 100--recipe-format.md           →  /pekit/reference/recipe-format
├── 200--supporting-files.md        →  /pekit/reference/supporting-files
└── 300--cli.md                     →  /pekit/reference/cli
```

The `4` orders this topic among its siblings; `reference` is the URL segment. Articles carry the same `<order>--<slug>` grammar, and their order prefixes decide reading order — the sidebar, the previous/next links, and the order they appear in the topic's single-page view.

Numbering in hundreds is the convention across this site. It is not a rule — `1--`, `2--`, `3--` works identically — but it means you can insert `150--` between two articles without renaming anything.

## The config

A topic's `trail.toml` is optional, and holds at most two keys:

```toml
# 4--reference.topic/trail.toml
title = "Reference"
```

Without it, the title is derived from the slug: `4--reference.topic` becomes "Reference", `2--writing-tests.topic` becomes "Writing tests". Write the file when that derivation is wrong — an acronym, a proper noun, unusual casing — or when the topic needs `inline_ref` phrases, which claim text that should auto-link to the topic's first article. See [Inline references](/trail/writing/inline-references.md).

## A topic has no page

This is the one surprising thing about topics. There is no page at `/pekit/reference` — the topic is not a destination, it is a grouping.

That has three consequences:

- **A topic appears as a card** on its product's or anthology's page, listing its articles (all of them when there are four or fewer, otherwise the first three plus a "See all" link) with a count and its total reading time.
- **Links land on the first article.** Every surface that shows a topic — its card heading, its "See all" link, the sidebar heading on an article page — points at the topic's first article in reading order.
- **A topic is not a `~link` target.** `~pekit/reference` resolves nothing, because `reference` is not the last segment of any page's path. Link to the article you mean: `~pekit/reference/cli`.

What *does* exist at the topic's path is its single-page view: `/pekit/reference/print` renders every article in the topic as one long page, and `/pekit/reference/print.md` is the same thing as markdown. See [The output surface](/trail/building/the-output-surface.md).

## Subfolders

A topic that has grown past a comfortable sidebar can group runs of articles into **subfolders** — plain `<order>--<slug>` directories, with no type suffix:

```text
2--concepts.topic/
├── 100--objects-and-identity.md          →  /ud/concepts/objects-and-identity
├── 200--the-schema-model.md              →  /ud/concepts/the-schema-model
└── 300--replication/                     a subfolder
    ├── trail.toml                        optional
    ├── 100--topology.md                  →  /ud/concepts/replication/topology
    └── 200--conflicts.md                 →  /ud/concepts/replication/conflicts
```

A subfolder:

- **adds a URL segment**, unlike a shelf;
- **has no page of its own**, like a topic — links from the sidebar open its first article;
- **renders as a collapsible group in the sidebar**, expanded automatically when the article being read is inside it;
- **may hold `trail.toml`, articles, `.link` files and images — but not another subfolder.** Subfolders are exactly one level deep. A topic needing more nesting than that is either two topics or a book.

Its optional `trail.toml` takes the same `title` and `inline_ref` keys a topic's does, and its title derives from its slug the same way.

An empty subfolder is tolerated and simply not shown, so you can create the directory before its articles exist.

## The sidebar

On an article page, the sidebar shows the article's own topic: the topic title (linking to its first article) above the topic's contents in reading order, with subfolders as collapsible groups and the current article marked. It shows one topic — not the whole product — because the topic is the unit a reader is working within.

Below it, "On this page" lists the article's own `h2` and `h3` headings, and highlights the one currently in view.

## Reading order and the pager

The prev/next links at the foot of an article step through the whole topic in reading order, subfolder contents flattened in place. The last article of one topic does not lead to the first of the next; the pager is a topic-local device.

## Topic or book?

| Use a topic when | Use a book when |
|---|---|
| Articles can be read in any order | The document is read in order, or cited by section |
| No page needs to say "§2.4" | Sections need stable numbers |
| Grouping is for navigation | The whole thing is one document with a cover |
| One level of subfolders is enough | Nesting goes deeper than two levels |

Almost all documentation is topics. Books are for specifications, formal references and manuals — see [Books](/trail/structuring-a-site/books.md).

---

# Books

_Trail / Structuring a site_

> A book is a formal, ordered document — a specification or manual — with a cover page, dotted section numbers derived from directory names, chapters nesting to any depth, and lettered appendices.

A **book** is a document read in order and cited by section: a specification, a formal reference, a manual. Where a [topic](/trail/structuring-a-site/topics-and-folders.md) is a set of related pages, a book is one document that happens to be split across pages.

Books get three things topics do not: a cover page, stable section numbers derived from the directory structure, and appendices.

## The directory

A book is a directory named `<order>--<slug>.book`, sitting in a product, an anthology or a shelf:

```text
1--pgss.book/                    →  /demo/pgss   (the cover)
├── trail.toml
├── 1--introduction.md           §1   →  /demo/pgss/introduction
├── 2--logon/                    §2   a chapter
│   ├── trail.toml
│   ├── 1--overview.md           §2.1 →  /demo/pgss/logon/overview
│   └── 2--flow.md               §2.2
└── a1--references.md            Appendix A
```

Its `trail.toml` requires a title and a description:

```toml
# 1--pgss.book/trail.toml
title = "Peios Generic System Standards"
short = "PGSS"
description = "Cross-platform system standards from the Peios Project"
```

| Key | |
|---|---|
| `title` | Required. The full name, shown on the cover and in cards. |
| `description` | Required. The standfirst on the cover, the card text, and the `llms.txt` entry. |
| `short` | Optional. An abbreviation — usually an acronym — used where the full title will not fit: the sidebar heading, the pill on the book's card, and the line above the title on the cover. |
| `inline_ref` | Optional. Phrases that auto-link to this book, and which may carry a `§` section suffix in prose. See [Inline references](/trail/writing/inline-references.md). |

## Section numbers come from the directory names

This is the part worth reading twice. **A book's section numbers are its order prefixes**, joined with dots along the path from the book root:

```text
2--logon/            →  §2
  1--overview.md     →  §2.1
  3--errors/         →  §2.3
    1--codes.md      →  §2.3.1
```

Two consequences follow:

- **Number books from 1, not 100.** The hundreds convention used for [topic articles](/trail/structuring-a-site/topics-and-folders.md) would produce §100 and §200. In a book the prefix is the published section number, so `1--`, `2--`, `3--` is what you want.
- **Gaps show through, on purpose.** If `2--` is deleted the book goes §1, §3 — because in a specification, section numbers are addresses. Renumbering to close a gap silently invalidates every citation anyone has ever written; leaving the gap is the honest outcome. Renumber deliberately, or not at all.

Inside an article, `h2` and `h3` headings continue the numbering as real text: in §2.1, the first `h2` is §2.1.1 and its first `h3` is §2.1.1.1. Headings deeper than `h3` are not numbered. The numbers are rendered into the heading itself rather than drawn with CSS counters, so they can be searched, selected and copied.

## Chapters

A chapter is a plain `<order>--<slug>` directory — no type suffix, exactly like a [topic subfolder](/trail/structuring-a-site/topics-and-folders.md) — except that chapters may nest as deeply as the document needs.

A chapter:

- **contributes a URL segment and a section number**;
- **has no page of its own** — links to it open its first article;
- **must contain at least one article, somewhere beneath it.** An empty chapter is a build error, because it would appear in the contents as a number leading nowhere;
- takes an optional `trail.toml` with `title` and `inline_ref`, with the title otherwise derived from the slug.

## Appendices

An entry whose order is written `a<N>--` is an **appendix**: lettered instead of numbered, and sorted after every numbered sibling at its level.

```text
1--pgss.book/
├── 1--introduction.md      §1
├── 2--logon/               §2
├── a1--references.md       Appendix A
└── a2--glossary/           Appendix B
    └── 1--terms.md         §B.1
```

- Letters run `A`, `B`, … `Z`, `AA`, `AB`, and so on.
- The numbering is by `a<N>` order, not position: `a1--` is A, `a2--` is B. Appendix numbering starts at `a1`; `a0--` is an error.
- Appendices work at **any** level, not just the book root. An appendix chapter inside a numbered chapter gives §2.A, and its articles §2.A.1.
- Where the entry itself is displayed — the sidebar, the contents — it is labelled "Appendix A" in full. In section references it is just the letter.

## The cover page

A book's URL is its cover: the product and anthology breadcrumbs, the `short` name if it has one, the title, the description, and the book's total reading time and last-updated date. The contents are the sidebar tree beside it — the whole book, chapters as collapsible groups, section numbers on every entry.

The tree remembers which chapters you opened, per book, as you move between pages.

## Frontmatter is different inside a book

Book articles use a reduced frontmatter set. `title:` is still required; `description:`, `related:`, `inline_ref:`, `updated:` and `reading_minutes:` all still work.

**`type:` is an error inside a book.** The concept/how-to/reference taxonomy describes how to approach a page, and inside a formal document that question is already answered — you read it in order. Trail rejects the key rather than letting it sit there meaning nothing.

## Citing sections

Books are the reason [inline references](/trail/writing/inline-references.md) exist. A book that claims a phrase can be cited by section from anywhere in the site:

```markdown
Every token MUST carry a lifetime, per PGSS §2.1.
```

"PGSS" links to the book; "PGSS §2.1" links to the exact section, resolving through the book's index of section numbers — including numbers that belong to a heading inside an article, not just to the article itself. Within a book's own pages, a bare `§2.1` resolves the same way against the surrounding book.

Because a section number is an address, this is where the "gaps show through" rule earns its keep.

## When a book is the wrong answer

A book is a commitment: numbered sections that readers may cite, an order that means something, and a cover page. Most documentation is not that. If your sections would never be cited by number, and the pages can be read in any order, you want a topic.

---

# Link aliases

_Trail / Structuring a site_

> A .link file places an existing page in a second location — same content, second URL, canonical pointing home. How to write one, what it may target, and why the alias stays out of the search index.

Some pages belong in two places. A "Signing and provenance" article that lives in pekit's *Running* topic is also the page a reader of the security anthology goes looking for; a specification's terminology section is also an appendix of the manual next to it.

A **`.link` file** places an existing page at a second location. The content is not copied — it is the same article, rendered again at a second URL, with its canonical URL still pointing at the original.

## Writing one

A link is a file named `<order>--<slug>.link`, holding TOML:

```toml
# 3--signing.link
target = "~pekit/running/signing-and-provenance"
title = "Signing and provenance"
```

| Key | |
|---|---|
| `target` | Required. A [`~` page reference](/trail/writing/links-and-references.md), in exactly the grammar body links use. It must start with `~`. |
| `title` | Optional. The title the aliased page carries *here*. Without it, the title is derived from the link's own slug. |

The `<order>--<slug>` prefix works exactly as it does for an article: the order places the alias among its siblings, and the slug becomes its URL segment. The alias does not inherit the target's slug, its order, or its title — it is a new entry in a new place that happens to render the target's body.

## Where a link may live

`.link` files sit wherever articles sit: in a topic, in a topic subfolder, in a book, or in a book chapter. They may not sit in a product, an anthology or a shelf.

What each may target:

| In a | May target |
|---|---|
| Topic | an article, **or a whole topic subfolder** |
| Topic subfolder | an article |
| Book or chapter | an article |

Aliasing a subfolder from a topic clones the entire folder into that topic's URL space — every article in it becomes an alias of its own original, under the new folder's slug. It is the one case where a single link file produces more than one page.

A link may never target another link. That would make the canonical chain ambiguous, so trail rejects it.

## What the alias page is

The aliased page renders exactly like the original: same body, same images, same headings. What differs:

- **Its URL and title** are the link's, not the target's.
- **Its canonical URL is the original's.** Search engines are told which of the two URLs is the real one, so the duplicate does not compete with it.
- **It is not in the search index.** Searching finds the original; the alias exists for people navigating the tree.
- **It claims no `inline_ref` phrases.** The original keeps them — a phrase must have exactly one destination.
- **"Edit this page" points at the original's source file**, because that is the file to edit.
- Inside a book, an alias gets a section number from its own order prefix like any other entry, may be an appendix (`a<N>--`), and carries no `type:` or `description:` — book entries never do.

## Example

Pekit's signing article lives in its *Running* topic. The security anthology wants it too:

```text
pekit.product/3--running.topic/
└── 600--signing-and-provenance.md        →  /pekit/running/signing-and-provenance

peios.product/1--security-fundamentals.antho/4--supply-chain.topic/
├── 100--overview.md
└── 200--pekit-signing.link               →  /peios/security-fundamentals/supply-chain/pekit-signing
```

```toml
# 200--pekit-signing.link
target = "~pekit/running/signing-and-provenance"
title = "Signing in pekit"
```

Both URLs work. Both show the same prose. Search returns the pekit one. Editing either takes you to the same source file.

## When not to use one

An alias is right when one piece of writing genuinely belongs in two navigational places. It is the wrong tool for:

- **A cross-reference.** If you just want to point at another page, write a [`~link`](/trail/writing/links-and-references.md) in the prose, or add it to the article's `related:` list.
- **A page that should differ between the two locations.** An alias is the same article; there is no way to vary it. Write two articles.
- **A rename.** Aliases are not redirects — the old URL still has to exist as a `.link` file forever. If a page has moved for good, move it and fix the links; trail will tell you which ones broke.
