Authoring pages
A page is a folder: pages/<slug>/+Page.mdx renders at /<slug>
(nested folders nest the URL). Every page starts with a YAML block,
and those fields are the whole authoring contract — URL, sidebar,
search, and the LLM artifacts all derive from them. There is no nav
config to edit. The parsed shape is exported as
PageMeta.
Directory layout = URL
Every page is a +Page.mdx inside a folder; the folder path is the
URL:
index is special — it maps to the site root /.
Frontmatter fields
| Field | Type | Default | Effect |
|---|---|---|---|
title | string | folder name | Sidebar label, <title>, breadcrumbs, search result title. |
section | string | '' | Sidebar group. New section strings just work — order them via sectionOrder in Site config. |
order | number | 99 | Global sort key: sidebar position within the section AND the prev/next sequence. |
description | string | — | <meta description>, search result blurb, llms.txt link blurb. |
draft | boolean | false | "Awaiting review" chip in the sidebar; page stays visible. |
hidden | boolean | false | Out of sidebar/search/prev-next until dev mode (Cmd+Shift+D). Still reachable by URL. |
noindex | boolean | false | Emits noindex, nofollow robots meta; excluded from pagefind and every LLM surface. |
dev | boolean | false | Shorthand for hidden: true + noindex: true — an internal developer note in one flag (studio's convention). |
tocLevel | 2 | 3 | 3 | 2 limits the right rail to H2 headings. |
fullscreen | boolean | false | Full-viewport page: no content column, TOC, or footer. |
A standard page:
An internal note, invisible to readers, robots, and agents:
Conventions for order
Leave gaps (0, 1, 2 … 10, 11 … 20, 21) so pages can slot in without renumbering a whole section. This site numbers sections in tens.
Keep values plain strings — the generator that builds the LLM
artifacts parses frontmatter with a simple flat key: value reader.
Nested YAML structures will not survive the trip.
Sidebar auto-discovery
The rules, in full:
- Pages group by their
sectionstring. Sections render in thesectionOrderyou pass toinitDocs; sections not in that list fall to the end, alphabetically — a new section shows up without any config change. - Within a section, pages sort by
order(missingorder= 99). Leave gaps between sections' order ranges (this site uses 0–4, 10–13, 20–23, …) so inserting a page never renumbers its neighbors. - If the site declares tabs, the sidebar shows
only pages whose URL falls under the active tab's
urlPrefix. hidden: truepages stay out of the sidebar (and prev/next) until the reader toggles dev mode with Cmd+Shift+D.
Adding a page is: create the folder, write frontmatter, done. Moving a
page is: move the folder. Renaming a section is: change the string in
the pages that use it (and sectionOrder if you pinned it).
Naming conventions
- Folder names are kebab-case; they become URL segments.
- Keep
sectionstrings short — they render as uppercase mono labels. - One H1 per page, matching (or elaborating) the frontmatter title. The H1 drives the topbar's brand-to-breadcrumb crossfade.
##headings feed the right-rail TOC; keep them scannable and front-loaded (they are also the anchors search results deep-link to — see the search guide).
Markdown & MDX
Pages are MDX: GitHub-flavored markdown, plus imports and JSX where prose is not enough. The MDX component map restyles every primitive (headings, links, tables, code) to the shell's design — write plain markdown and it comes out right.
Headings and links
- Headings get stable slug ids (rehype-slug); hover a heading to grab
its anchor. H2/H3 feed the TOC in the right rail
(
tocLevel: 2drops the H3s). - Internal links are root-relative (
/guides/search) — the client router intercepts them; the LLM generator rewrites them to.mdtwins in the exported artifacts.
Code fences
Fences are highlighted by shiki with dual light/dark themes. The meta
string takes a file="…" chip:
- The language chip comes from the fence language.
- The
:set nubutton toggles line numbers site-wide — flip it on one block and every block follows. - Copy grabs the raw text.
Callouts
<Callout> is in scope without an import (as are <Preview>,
<StatusTable>, and <TestStatus>):
See the Callout page for variants.
Tables
GFM tables render with the template's hairline borders:
Live examples
For component demos, follow the Preview
convention: a real component in examples/, imported twice — once as
a module to render, once with ?raw to show its own source:
Images and assets
Files in public/ serve from the site root (/diagram.png). Prefer
SVG; both themes should read well — test with the theme toggle (see
Theming & CSS).