Repo: website-docs.lemonfiber.app
Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page
Status: Proposed
The documentation site at docs.lemonfiber.app. Astro Starlight, static,
Hippocratic 3.0. It is for an operator or an integrator following instructions, in
two topics: Use and Build on. Almost nothing it publishes is written here — the
pages are each repo’s own documentation, pinned to a revision and rendered
(ADR-0015).
The specification is rendered on the frontpage and contributor
material on the contributor site
(ADR-0040).
Implements: the org’s user-facing documentation and the build-in-the-open
commitment of governance; consumes brand
(roadmap).
Why this is a separate repo
The same floor that made the org multi-repo
(ADR-0004), plus one thing the
frontpage cannot give it. The two sites have opposite relationships with time: the
frontpage reads live org state at build so that it cannot lag
(REPO-R39), while documentation must render a pinned revision, because a reader
following instructions needs the instructions that match the release they installed.
One repo cannot honour both rules. Folding this into website-lemonfiber.app would
also mean rebuilding Starlight’s sidebar, search and version switcher inside a bespoke
site that has no use for them.
It is not folded into spec either. spec is where the specification is written and
checked; what an operator follows is written in the repositories that build it.
The one property to remember
It renders; it does not own. Every page of documentation belongs to the repository that also holds the thing it describes, and reaches this site as a git submodule pinned to an exact revision, symlinked into a Starlight content collection. Nothing is fetched during a build.
- the core’s generated command reference and its contract artefacts
- each SDK’s guide, and the plugin template
.github— conduct, security, where to ask
This is what makes the pages trustworthy: they cannot quietly drift from the repo they document, because they are that repo’s files at a revision the site names on the page.
Every authored page declares which of the two topics it serves, and the navigation is built per topic from that declaration. A page that restates a page another repository owns is a second copy that drifts; that page is mirrored instead.
What is written here is the connective tissue — navigation, landing pages, and the task-shaped guides that mirrored prose does not provide because it was written for a repository rather than for a reader arriving from a search box.
Project status is not here. The roadmap, the board, what is built and the list of releases change whenever the org does, and they live on the frontpage, which reads them live. This site renders pinned revisions for a reader following instructions, so a page of project status here would be as old as its pins. A route that held one redirects to the frontpage’s page for it.
What’s in it
website-docs.lemonfiber.app/
├── .gitmodules the pins — one per repo whose docs are shown
├── vendor/ the submodules themselves, never edited here
├── mirrors.json the route table — which upstream file each page is
├── src/content/docs/ the collection; this site's own pages, and mirrored
│ trees entering by symlink beside them
├── src/lib/ the mirror loader: routes, provenance, link rewriting
├── messages/en.json the message catalogue; every authored string
├── src/components/ VersionTrain · VersionPill · StatusPill · …
└── astro.config.ts Starlight: sidebar, one locale, link validation
Authored and mirrored pages share one collection rather than sitting in separate
trees: Starlight’s sidebar is built from route, so a split would mean two sources
for one navigation. A mirrored page is a symlink into vendor/, which is what
makes “this site holds no second copy” (REPO-R45) a property of the filesystem
rather than a habit.
How it stays fresh
Deployed by CI to Cloudflare, as an assets-only Worker that wrangler.jsonc
declares and wrangler uploads, and to GitHub Pages while the domain still points
there, from a checkout that includes submodules. The headers the host sends are
in the _headers file the build carries. A pin moves
by pull request in this repo, which is what makes the change reviewable and dated: the
diff says which revision the site will start showing, and every rendered page carries
that revision and its date so a reader can tell how old the words are. A build fetches
nothing, so it succeeds offline and renders the same site from the same commit a year
later.
Two pin sets stand behind the published site. next is the submodule pins, moved by
pull request as above. The stable set, pins/stable.toml, is what the newest released
version recorded: the core at its release tag, each embedded repository at the commit
the version’s manifest names under pins, and every other repository at its default
branch’s last commit on or before the version’s released_on, which git answers for a
release that recorded nothing about it. A reader following instructions for the release
they installed gets the pages that release shipped with.
Every minor from 0.16.0 on is kept. When a version is cut, the site is built at its
stable pins under /v<major>.<minor>/ and the build is frozen as a release asset of
this repository; it is never rebuilt. A deploy builds two sites, the newest stable at
/ and next at /next/, and puts each frozen build at its path beside them. 0.16.0
is the first kept because it is the first release with plugins, the first surface
written against by authors outside the organisation.
Maintenance
Bumping pins, and the site’s own structure and styling. Nothing else: a wrong sentence
is fixed in the repo that owns it, which is slower and is the behaviour worth buying.
Structural change, like any other, cites a spec identifier
(GOV-R2). CI reuses the
shared workflows (spec-check, hygiene, security, dco, commitlint, labeler)
exactly as every other repo does (Q-R56), and adds a link check that reads mirrored
prose as well as authored prose — this is the only build that sees all of it at once.
Requirements
| ID | Requirement |
|---|---|
| REPO-R45 | Every documentation page MUST be rendered from the repository that owns its source; this repository MUST NOT hold a second copy of it. |
| REPO-R46 | Mirrored content MUST be pinned to an exact upstream revision recorded in this repository, never to a branch. |
| REPO-R47 | A build MUST NOT fetch content over the network; everything it renders MUST already be in the checkout. |
| REPO-R48 | Every link in mirrored content MUST resolve to a page on this site or to a document that is reachable elsewhere, and CI MUST fail on one that does not. |
| REPO-R49 | Every mirrored page MUST show the upstream revision it was rendered from, and that revision’s date. |
| REPO-R50 | Every user-facing string authored in this repository MUST come from the message catalogue and MUST NOT be written into a template. |
| REPO-R51 | The published site MUST load no font, script, style or tracker from a third party at run time. |
| REPO-R52 | Superseded by REPO-R79: the specification is rendered on the frontpage, at the revision the board snapshot read. The number is not reused. |
| REPO-R53 | A URL that this site or a retired rendering of the specification published MUST continue to resolve, by redirect, to the page that replaced it, including a page that moved to the frontpage. |
| REPO-R68 | The site MUST NOT render project status: the roadmap, the board, what is built and the list of releases are the frontpage’s to publish. |
| REPO-R80 | The site MUST NOT render the specification or contributor material; a route it published for either MUST redirect to the page that replaced it on the frontpage or the contributor site. |
| REPO-R81 | Every authored page MUST declare its topic, use or build; the navigation MUST be built per topic from that declaration, and a check MUST refuse a page with none or one under the other topic’s tree. |
| REPO-R82 | An authored page MUST NOT restate a normative page another repository owns; that page MUST be mirrored instead. |
| REPO-R83 | The build MUST publish a provenance index mapping every route it renders to the repository, the path and the revision it was rendered from. |
| REPO-R88 | The stable documentation MUST be rendered from the revisions the newest released version recorded: the core at the tag it was released as, each embedded repository at the commit the version’s manifest names under pins, and any other repository at its default branch’s last commit on or before the version’s released_on. A check MUST refuse a stable pin that is none of these. |
| REPO-R89 | Every minor version from 0.16.0 on MUST be published under /v<major>.<minor>/ from a build frozen when the version was cut and kept as a release asset of this repository; the newest stable MUST be published at / and the submodule pins under /next/, and a deploy MUST build only those two. |
| REPO-R90 | Every page MUST carry a switcher naming every published version and linking to the same route in each version that serves it, and each version MUST be searched on its own. |
Related
- ADR-0015 The documentation site renders content it does not own
- ADR-0004 Four-repo split
- ADR-0040 Three sites, each for one reader
- website-lemonfiber.app — the frontpage, which reads live state rather than a pin, and renders the specification
- website-contribute.lemonfiber.app — the contributor site
- brand — the tokens the site consumes
- 50-governance — the transparency commitment it serves
- website-kit — the mirror machinery this site takes by commit