Peios Learn
Products
PePeios pkpekit PvProvium UDUniversal Directory TrTrail PrProject WiWispist
Using Peios Security Basics Technical Documentation Source
Using Peios Security Basics Technical Documentation Source
Trail

Writing

Single-page view · as markdown

Articles and frontmatter

Trail / Writing

An article is a single .md file named <order>--<slug>.md: a YAML frontmatter block, then markdown.

---
title: Quick start
type: how-to
description: Build and package a tiny "hello" program with pekit, from an empty directory.
related:
  - pekit/getting-started/what-is-pekit
  - pekit/recipes/anatomy
---

This page takes you from an empty directory to a working `.peipkg`…

The frontmatter is required and must be the first thing in the file: a line of exactly ---, the YAML, and a closing ---. A file that does not start with ---, or whose block is never closed, is a build error. So is any key not listed below — a typo'd descripton: fails the build rather than silently doing nothing.

The keys #

KeyRequired
titleyesThe page's name: its h1, its breadcrumb, its sidebar entry, its search-result heading, its og:title.
typein topicsThe learn taxonomy — concept, how-to, reference on this site. An error inside a book.
descriptionnoOne sentence. Becomes the page's meta description and social-preview text.
relatednoPage references shown as a "Related Content" list at the foot of the page.
inline_refnoPhrases that auto-link to this page wherever prose states them.
updatednoAn ISO YYYY-MM-DD date.
reading_minutesnoOverrides the estimated reading time.

title #

The only key every article must have, in topics and books alike. It is not derived from the slug — unlike a topic or chapter title, an article states its own.

type #

Required on every article in a topic, and rejected on every article in a book.

Trail does not constrain the value or display it on the page; it is carried through to site.json for tooling that wants to filter by it. What it is really for is the author: deciding whether a page is a concept (explaining how something works), a how-to (walking through a task) or a reference (exhaustive, looked-up rather than read) is a genuinely useful discipline, and pages that cannot answer the question are usually two pages.

Inside a book the question is already answered — a specification is read in order — so trail rejects the key rather than let it sit there meaning nothing.

description #

Optional, but write one. It becomes:

  • the page's <meta name="description"> and og:description, which is what search engines and chat apps show;
  • the standfirst line in the page's markdown mirror;
  • the description field in site.json.

It is not displayed on the page itself, and it is not the in-site search snippet — Pagefind builds those from the body text around the match.

Build with --strict to make a missing description a build failure. Alias pages are exempt, since the original carries it.

related #

A list of page references, in the same grammar body links use but without the leading ~:

related:
  - pekit/running/invocation
  - peios/package-management/overview

They render as a "Related Content" list under the article, and they appear in the page's markdown mirror and in site.json. Resolution is as strict as a body link: an ambiguous reference always fails the build, and a missing one fails unless --allow-dangling-links is set, in which case it warns and drops from the list.

inline_ref #

Phrases that should become links to this article wherever they appear in the site's prose:

inline_ref:
  - PCDS GUID
  - PCDS GUIDs

Every occurrence in ordinary prose, anywhere on the site, links here — except on this page itself. Phrases are claimed site-wide and exclusively; two pages claiming the same phrase is a build error. See Inline references.

updated #

An ISO date, and validated as one — 2026-05-01, not May 2026 and not 01/05/2026.

updated: 2026-05-01

It shows in the page's meta line, and it becomes the page's <lastmod> in sitemap.xml. It is deliberately manual: file modification times are noise (a whitespace fix is not an update, and a checkout rewrites them all), and trail does not read git history. An article with no updated: simply does not show one.

reading_minutes #

Trail estimates reading time from the body's word count at 200 words a minute, rounded up, with a floor of one minute. Code blocks count — they are read, just differently.

Set reading_minutes: when the estimate is wrong: a dense reference table reads far slower than its word count suggests, and a page that is mostly a long code listing far faster.

reading_minutes: 30

Roll-ups #

Reading times and dates add up the tree. A subfolder totals its articles; a topic totals its articles and subfolders; a book totals its chapters; an anthology totals its topics and books; a product totals everything in it.

  • Reading time is the sum, so a book's cover can say how long the whole book takes and a topic card can say how long the topic is.
  • updated is the most recent date anywhere beneath, so a container reflects its freshest page.

Roll-ups are computed after .link aliases are resolved, so an aliased article counts in the totals of the place it was linked into.

The body #

Everything after the closing --- is CommonMark with GitHub extensions: tables, strikethrough, footnotes, and > [!NOTE]-style admonitions. On top of that, trail adds:

  • ~page references — link by page identity instead of URL.
  • Co-located images — ![alt](diagram.svg) beside the article, with dimensions filled in and captions turned into figures.
  • Syntax-highlighted code blocks with copy buttons.
  • Tab groups and mermaid diagrams.
  • Inline references, § section citations and RFC-2119 keyword highlighting.

A few things happen to headings automatically: h2 and h3 become the "On this page" list, every heading gets a stable id and a permalink anchor, and inside a book they carry their section numbers as real text. Ids come from the heading text, with a numeric suffix if two headings on a page would otherwise collide.

Tables are wrapped in their own horizontally-scrolling container, so a wide table never makes the whole page scroll sideways.

Naming and ordering #

The filename is not decoration:

200--quick-start.md
 │        └── the URL segment, and what you write in a ~link
 └── the sort key among siblings — never shown, never in a URL

Two files sharing an order in the same directory is an error. Numbering in hundreds leaves room to insert later; inside a book the prefix is the published section number, so number from 1 there instead.

print is a reserved slug — every container publishes a /print page — so 100--print.md is rejected.

Links and references

Trail / Writing

Trail links pages by identity, not by URL. Instead of writing a path that breaks the moment a page moves, you write a ~ reference naming the product and enough of the page's slugs to be unambiguous:

See [Commands and targets](~pekit/running/commands-and-targets) first.

Reorganise the tree — move that topic into an anthology, wrap it in a shelf, renumber it — and the link still resolves. Delete the target, and the build fails and tells you every page that pointed at it.

The grammar #

~<product-slug>[/<segment>]…[#<fragment>]
  • The first segment is always a product slug. There is no relative form and no site-wide search; every reference says which product it means.
  • The remaining segments match the end of a page's path. Trail compares them against each page's slugs — the anthology slugs, the topic slug, any subfolder or chapter slugs, and the page's own — and matches if your segments are the tail of that list.
  • Exactly one page must match. Zero or several is an error.
  • A fragment may follow, and is appended to the resolved URL: ~pekit/reference/cli#global-flags.

The rule of thumb is: write the shortest thing that is unambiguous, and add segments from the left only when you have to.

A worked example #

Given this page:

/peios/security-fundamentals/identity/tokens/issuing
        └ anthology ───────┘ └ topic ┘ └folder┘ └page┘

all of these resolve to it:

~peios/issuing
~peios/tokens/issuing
~peios/identity/tokens/issuing
~peios/security-fundamentals/identity/tokens/issuing

~peios/issuing is the one to write — until a second page in peios is also called issuing, at which point that reference becomes ambiguous, the build fails, and you add a segment.

Note that the deeper segments are for disambiguation only. A chapter or subfolder slug can appear in a reference even though it is not a page you could link to on its own.

What can be a target #

TargetableReference
A productyes~pekit
An anthologyyes~peios/security-fundamentals
A book coveryes~peios/pgss
An articleyes~pekit/reference/cli
A topicnolink to an article in it
A topic subfolderno(except as a .link target)
A book chapternolink to an article in it
A shelfnoit has no page at all

Topics, subfolders and chapters have no page of their own, so there is nothing for a reference to land on. Link to the article you actually mean.

Ordinary links still work #

A ~ at the start of a destination is what makes it a reference. Everything else is left alone:

[the CommonMark spec](https://spec.commonmark.org)     external, untouched
[the sitemap](/sitemap.xml)                            root-relative, untouched
[this section](#the-grammar)                           same-page fragment

Root-relative links are the escape hatch for the handful of URLs that are not pages — /print views, /llms.txt, /site.json. They are not checked, so they are also the way to ship a broken link. Prefer ~ wherever the target is a page.

~ is only meaningful in a link destination. In an image destination it is an error, with a message saying so: images are files, addressed relative to the article.

Where else references are used #

The same grammar appears in three other places:

# an article's frontmatter — no leading ~
related:
  - pekit/running/invocation
# a .link alias file — with the ~
target = "~pekit/running/signing-and-provenance"

# the root trail.toml's nav — with the ~, or an external URL
[[nav]]
label = "Specs"
url = "~peios/pgss"

The related: list is the odd one out in dropping the ~; everything else keeps it.

When a link breaks #

Every link in the site is checked on every build, and all the failures are reported together — one build tells you the whole story rather than stopping at the first bad reference.

Error: 3 broken links:
in article '/pekit/recipes/anatomy': link '~pekit/running/invokation' matches no page in product 'pekit'
in article '/peios/identity/sids': link '~pekti/overview' names unknown product 'pekti'
in article '/pekit/reference/cli': link '~pekit/targets' is ambiguous; candidates:
  ~pekit/running/commands-and-targets/targets
  ~pekit/reference/recipe-format/targets

There are three failure kinds, and they are not treated alike:

MeansWith --allow-dangling-links
Unknown productthe first segment is not a product slugwarning
No matchnothing in that product ends with those segmentswarning
Ambiguoustwo or more pages matchstill fatal

Ambiguity is never downgradable. A missing target is a link that does nothing; an ambiguous one is a link that goes somewhere specific and possibly wrong, and only the author knows which page was meant.

--allow-dangling-links is for the middle of a refactor, when you have moved a hundred pages and want to see the site before fixing every reference. It is not a setting to leave on.

References in print views and mirrors #

The single-page and markdown views rewrite references so they still work away from the site:

  • In a /print bundle, a reference to a page inside the same bundle becomes an in-document anchor, so the whole document navigates itself. A reference to a page outside it becomes an absolute URL when the site config has a url, and stays root-relative otherwise.
  • In a .md mirror, a reference becomes the target's own .md URL, so a reader following links through the markdown surface stays in it.

Images

Trail / Writing

Images live beside the articles that use them. There is no assets directory to maintain and no separate URL scheme to remember: drop the file in the same folder as the .md, and reference it by name.

2--logon.topic/
├── 100--overview.md
└── logon-flow.svg
![The logon sequence](logon-flow.svg)

The image publishes at the URL of the directory it was found in, keeping its own file name — here /peios/logon/logon-flow.svg. Move the folder and the image moves with it.

Referencing #

Destinations resolve relative to the article's own .md file, exactly as an editor's markdown preview resolves them. Relative paths may climb out of a subfolder with .., so a diagram shared by a folder's worth of articles can sit one level up:

2--concepts.topic/
├── shared-diagram.svg
└── 300--replication/
    ├── 100--topology.md          ![](../shared-diagram.svg)
    └── 200--conflicts.md         ![](../shared-diagram.svg)

Three kinds of destination are left exactly as written and never checked: absolute URLs (https://…), root-relative paths (/…) and data: URIs.

A ~ reference in an image destination is a build error. ~ names pages, not files.

Where images may sit #

Anywhere articles may sit: a topic, a topic subfolder, a book, or a book chapter. Not in a product, anthology or shelf directory — those hold only trail.toml and subdirectories.

The file name must be a valid slug plus a lowercase extension: logon-flow.svg, not Logon Flow.SVG. Recognised extensions are:

png   jpg   jpeg   gif   svg   webp   avif

Anything else in an article directory is an "unexpected file" error — which is the point. A .pdf or a .xlsx sitting in a content folder is almost always a mistake, and trail would rather say so than quietly ignore it.

Dimensions #

Trail reads each raster image's header at build time and emits real width and height attributes:

<img src="/peios/logon/screenshot.png" alt="The logon prompt" width="1280" height="720">

The browser can then reserve the right space before the file arrives, so text does not jump around as images load. SVGs get no dimensions — they scale — and neither does any file whose header cannot be read.

Captions and figures #

An image with a title — the quoted string after the destination — that sits alone in its own paragraph becomes a <figure> with a <figcaption>:

![Three services exchanging tokens](logon-flow.svg "How a logon token reaches the session service")
<figure>
  <img src="/peios/logon/logon-flow.svg" alt="Three services exchanging tokens">
  <figcaption>How a logon token reaches the session service</figcaption>
</figure>

The two strings do different jobs and should say different things. The alt text describes the image for someone who cannot see it. The caption is prose everyone reads, and can say what the diagram is for.

An image without a title, or one sharing its paragraph with other text, renders as an ordinary inline <img>.

Unreferenced images #

Only images some article actually references are copied into the output. One that nothing references prints a warning and is left out:

warning: image '/…/2--logon.topic/old-diagram.png' is not referenced by any article and was not published

A warning rather than an error, deliberately: adding the file before the article that will use it is a normal way to work. But a warning that stays warning is a file to delete.

A referenced image that does not exist is the other way round — a broken link, fatal unless --allow-dangling-links downgrades it:

in article '/peios/logon/overview': image 'logon-flow.svg' not found (resolved relative to the article's folder)

In the other views #

Images work in the markdown mirrors and /print bundles too: since those serve an article's body away from its own folder, relative destinations are rewritten to the image's published URL.

Diagrams #

For flowcharts, sequence diagrams and the like, consider a mermaid code block instead of an image file. Mermaid diagrams are text — diffable, editable, and they follow the reader's light or dark theme, which a checked-in PNG cannot.

Code blocks

Trail / Writing

Fenced code blocks work as they do in any markdown, with an info string naming the language:

```rust
fn main() {
    println!("hello");
}
```

Trail highlights that at build time and wraps it with a copy button:

<div class="code-block" data-language="rust">
  <button class="copy-code" type="button" data-copy-code>…</button>
  <pre><code><span class="hl-storage hl-type hl-function">fn</span> …</code></pre>
</div>

Highlighting is classes, not colours #

Highlighting happens once, when the site is built — there is no highlighter shipped to the browser and no flash of unstyled code.

What is emitted is class names, not inline colours: hl-keyword, hl-string, hl-comment and so on, prefixed so they cannot collide with the theme's own classes. Those classes resolve through the same CSS custom properties as everything else on the page, which is why code follows the reader's light or dark choice instead of freezing one palette into the markup. Theming covers the tokens involved.

The copy button #

Every code block gets one. It sits in the top-right corner, appears on hover (and is always visible on touch devices), copies the block's text to the clipboard, and briefly says so.

Nothing is stripped from what it copies, so a $ prompt in a shell example is copied along with the command. Write shell examples without prompts if you would rather they paste cleanly.

Which languages are highlighted #

Trail bundles syntect as its highlighter, with the extended syntax collection from two-face — the same definitions bat ships, a little over two hundred of them. The info string is matched against a syntax's name or one of its file extensions, case-insensitively, so both rust and rs work.

Everything you are likely to reach for is covered:

bash / sh / fish / zsh   asm         awk          cmd / bat          c / c++ / c#
clojure    cmake         coffeescript   crystal    css / scss / sass / less / stylus
d          dart          diff         dockerfile  dotenv     elixir   elm
erlang     f#            f90          gd          gitconfig / gitignore
glsl       go / gomod    graphql      dot         groovy     haskell  hcl / terraform
html       http          idris        ini         java       js       jq
json / jsonnet           julia        kotlin      latex / bibtex      lean
lisp       llvm          lua          make        markdown   matlab   nginx
nim        nix           objective-c  ocaml       odin       orgmode  pascal
perl       php           protobuf     puppet      purescript python   qml
r          racket        rego         robot       ruby / haml / slim   rust
scala      solidity      sql          svelte      swift      systemverilog / verilog / vhdl
tcl        toml          typescript / tsx        typst       vim      vue
wgsl       xml / svg     yaml         zig

…alongside the config and system formats that turn up in documentation: crontab, fstab, passwd, resolv, syslog, ssh_config, known_hosts, .htaccess, requirements.txt, csv / tsv, manpage, strace, email.

Still absent: powershell, and the shell-session forms (console, shell-session). A console block renders as plain text — which is usually what you want anyway, since a $ prompt is not shell syntax.

An info string the set does not recognise is not an error and does not fail the build: the block renders as plain escaped code, with the same wrapper, the same copy button, and its language still recorded on it as data-language.

The definitions' licences ship with every build at /assets/LICENSE-Syntaxes.txt.

Blocks with no language #

A fence with no info string renders as escaped plain text, with the wrapper and copy button intact. Use one for output, trees and anything that is not a language:

```
built 1227 pages (8 products) → ./dist
```

Across this site the convention is text for that. The highlighter does not recognise text as a language, so it renders identically to a bare fence while reading more explicitly in the source.

Indented code blocks (four spaces) are supported too, and are treated as having no language.

Inline code #

Inline `code` is ordinary markdown and is not highlighted. It is also excluded from inline reference matching: a claimed phrase inside backticks stays plain text, so writing `PCDS GUID` when you mean the literal string does not produce a link.

In the other views #

Code blocks survive into the markdown mirrors and /print bundles as ordinary fenced blocks with their info strings intact — the mirrors reproduce your source, not the rendered HTML.

Admonitions, tabs and diagrams

Trail / Writing

Three constructs on top of ordinary markdown handle the things prose alone does badly: setting something apart, showing the same instruction several ways, and drawing.

Admonitions #

Admonitions use GitHub's alert syntax — a blockquote whose first line is a marker:

> [!IMPORTANT]
> **Pekit supersedes the old `peipkg-build` recipe system.** A pekit recipe
> is the current and only supported way to build a package.

Five kinds exist, and no others:

MarkerRenders asFor
> [!NOTE]NoteAn aside worth knowing, not worth interrupting for.
> [!TIP]TipA shortcut or a better way.
> [!IMPORTANT]ImportantSomething a reader who skims will regret missing.
> [!WARNING]WarningSomething that will go wrong.
> [!CAUTION]CautionSomething that will go irreversibly wrong.

The body is full markdown — lists, code blocks, links, all of it.

A blockquote whose first line looks like a marker but is not one of the five is a build error, not silently-rendered text:

unknown admonition type '[!WARN]' (expected NOTE, TIP, IMPORTANT, WARNING or CAUTION)

That is deliberate. A typo'd marker renders as a quotation with [!WARN] sitting at the top of it, which nobody proofreading their own page ever notices.

An ordinary blockquote — no marker — is still an ordinary blockquote.

Tab groups #

Tab groups show the same instruction several ways, so a page does not have to repeat itself per platform, per shell, or per package manager.

:::tabs
:::tab Linux
Install with your package manager:

```sh
sudo apt install trail
```

:::tab macOS

```sh
brew install trail
```

:::

The grammar is three markers, each alone on its own line:

Marker
:::tabsOpens a group.
:::tab <label>Starts a tab. The label is everything after the marker.
:::Closes the group.

The first tab is shown; the rest are hidden until selected. Each panel's body is full markdown, so a tab can hold code blocks, lists, admonitions and images.

Rules, all of them enforced at build time:

  • A group must be closed — an unclosed :::tabs is an error.
  • A group must contain at least one :::tab, and each :::tab needs a label.
  • Nothing but blank lines may appear between :::tabs and its first :::tab.
  • Groups cannot nest.
  • :::tab outside a group, or ::: with no group open, is an error.

Markers inside fenced code blocks are left alone, which is how this page can show the syntax without triggering it.

Note

Tab panels are hidden with the hidden attribute, so a reader searching the page with their browser's find-in-page will not see text in the tabs they have not opened. The site's own search indexes all of it. When printed, every panel is expanded and the buttons are dropped, so nothing is lost on paper.

Diagrams #

A code block tagged mermaid is rendered as a diagram in the browser:

```mermaid
sequenceDiagram
    Client->>Gate: request + token
    Gate->>Registry: check claims
    Registry-->>Gate: allow
    Gate-->>Client: 200
```

Any mermaid diagram type works — flowcharts, sequence diagrams, state diagrams, ER diagrams, Gantt charts, and the rest.

The mermaid library is a large script, so it is only shipped to pages that actually contain a diagram. A site with no diagrams anywhere never emits it at all.

The diagram is drawn in the reader's current theme, light or dark, chosen when the page loads. Switching theme afterwards re-styles the rest of the page but leaves already-drawn diagrams as they were until the page is reloaded.

Diagram or image? #

Prefer mermaid when the diagram is boxes, arrows and labels. It is plain text in your source: diffable, reviewable, editable by whoever is next in the file, and it follows the reader's theme.

Reach for an image when the thing is genuinely pictorial — a screenshot, a photograph, an illustration, or a diagram whose layout matters more than mermaid will let you control.

Inline references

Trail / Writing

Some terms should always be links. If there is one page explaining what a PCDS GUID is, then every "PCDS GUID" written anywhere on the site ought to point at it — and nobody wants to write that link by hand a hundred times, or notice the ninety-nine places it was forgotten.

An inline reference is a phrase a page claims. Trail then links every occurrence of that phrase in the site's prose to the claiming page, automatically.

Declaring a phrase #

Declaration is self-service: a thing declares the phrases that mean it, in its own file. There is no central glossary to maintain.

An article declares in its frontmatter:

---
title: Globally unique identifiers
type: reference
inline_ref:
  - PCDS GUID
  - PCDS GUIDs
---

Everything else declares in its trail.toml:

# 2--pgss.book/trail.toml
title = "Peios Generic System Standards"
short = "PGSS"
description = "Cross-platform system standards from the Peios Project"
inline_ref = ["PGSS", "Peios Generic System Standards"]

Phrases are matched literally, so plurals and alternative spellings are separate claims. List them all.

Where a phrase lands #

Declared onLinks to
An articlethat article
A productthe product's landing page
An anthologythe anthology's landing page
A bookthe book's cover — and § may reach a section
A topicthe topic's first article
A topic subfolderthe folder's first article
A book chapterthe chapter's first article

The pattern is: the declarer's own page, or — for the containers that have no page — the first article inside it. A container that declares a phrase but holds no articles to land on is a build error.

A shelf may not declare a phrase at all, since it has neither a page nor articles of its own. Declare it on the shelf's items.

Where phrases are matched #

In ordinary prose, and only there. Matching skips:

  • Headings, whose ids are derived from their text;
  • Link text — a phrase inside an existing link is left alone, so a deliberate link is never rewritten;
  • Image alt text;
  • Code blocks and inline code — writing `PCDS GUID` when you mean the literal string produces no link;
  • The claiming page itself, which never links to itself.

Two more rules make matching predictable:

  • Whole words only. A phrase surrounded by letters, digits or underscores does not match. "PCDS GUIDs" does not match inside "PCDS GUIDsomething".
  • Longest wins. When two claimed phrases overlap at the same position, the longer one is used — so "PCDS GUID" beats "PCDS", and a phrase does not get chopped up by a shorter one inside it.

Phrases are exclusive #

A phrase belongs to exactly one declarer, site-wide. Two things claiming the same phrase is a build error:

inline_ref phrase 'PCDS' is claimed by both book '/peios/pcds' and article '/peios/formats/pcds-overview'

That is the whole point: if two pages both want to own a term, the ambiguity is real and a reader would have been sent to the wrong one. Decide which page is the destination.

Empty phrases, phrases with leading or trailing whitespace, and phrases containing § are also errors. Link aliases never claim phrases — the original keeps them.

Choosing phrases well #

Inline references are powerful in the way find-and-replace is powerful. A phrase that is too common turns the site into a sea of blue.

  • Claim terms of art, not ordinary words. "PCDS GUID" is a term. "identity" is a word.
  • Claim what a reader would want defined. The test is whether someone meeting the phrase mid-sentence would benefit from a link.
  • Prefer the specific form. Claiming "GUID" catches every passing mention; claiming "PCDS GUID" catches the ones that mean your page.
  • Remember plurals and expansions — they are separate claims, and a term claimed in only one of its forms links inconsistently, which reads worse than not linking at all.

Section citations with § #

A phrase claimed by a book can be extended with a section number in prose:

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

"PGSS §2.1" becomes one link to that exact section. The suffix is a single space (or non-breaking space), the § sign, and a section label — digits, dots and appendix letters: §2, §2.1.3, §A, §B.2. A sentence-ending full stop is not part of the label.

Every book carries an index of its section numbers, covering:

  • articles, by their section number (§2.1 → that article's page);
  • chapters, by theirs (§2 → the chapter's first article);
  • headings inside articles — the h2 and h3 numbers trail generates (§2.1.3 → that article, at that heading).

So a citation can be as precise as a subsection of a page.

A § label that does not resolve is a build error — with the phrase still linked to the book, so the page is not broken while you fix it:

'PGSS §9.9' does not match any section of '/peios/pgss'

Like a broken ~link, it is downgraded to a warning by --allow-dangling-links.

Bare § inside a book #

Within a book's own pages, a bare § reference resolves against the surrounding book, with no phrase needed:

The requirements of §2.2.1 apply, except as noted in §A.

Unlike the phrase-qualified form, a bare § that does not resolve stays plain text and says nothing. That is not an oversight: specifications routinely cite sections of other documents, and a build that failed on every "§9.9 of RFC 3986" would be unusable. The qualified form names its book and so can insist; the bare form cannot, so it does not.

RFC-2119 keywords #

Requirement keywords are highlighted everywhere on the site, with no configuration and nothing to declare:

MUST · MUST NOT · REQUIRED · SHALL · SHALL NOT · SHOULD · SHOULD NOT · RECOMMENDED · NOT RECOMMENDED · MAY · OPTIONAL

They must be written in capitals, as RFC 2119 intends — the capitals are what distinguishes a requirement from the ordinary English word. Matching is whole-word and longest-first, so "MUST NOT" highlights as one keyword rather than as "MUST" followed by a stray "NOT", and it skips the same places phrase matching skips: headings, links, and code.

The styling is a weight and the product's accent colour, not a badge. It is meant to make a requirement scannable in a page of prose, and it works in ordinary articles as well as in books.

Peios Learn — documentation for the Peios project.

Built with Trail.