Context
Every docs site is on Mintlify (0002, 0299): Stackra core’sapps/docs at docs.stackra.figentra.com, and each product’s own apps/docs. Mintlify is a hosted product. It ships no
self-hosted export, so its build sits outside our Workers and its deploy needs its own Runway provider, branch and
GitHub app. It also gives each repository its own site, while Figentra’s readers want one place with a tab per product.
The product repositories are private, so a hub that checked them out at build time would need read access to all of
them, and would publish whatever sat on their main branch rather than what was released.
Decision
- Fumadocs, self-hosted and open source. Every Figentra docs site is built with Fumadocs and served by a Cloudflare Worker with static assets (0284). Fumadocs runs on Vite with React Router 7, prerendered to static files, because Next.js is rejected (0165). This replaces Mintlify everywhere: Stackra core, Figentra and every product.
- Runway deploys every site. A docs site is deployed through Runway, by its Cloudflare Workers provider (0289), never by a direct Cloudflare call. Dev and staging deploys run without the owner; production waits on the owner’s Environment approval (0468).
- Each repository writes its docs in its own
docs/. The pages sit indocs/at the repository root and are reviewed in the same pull request as the code they describe. - Each product release publishes a docs package. The product’s existing Release also publishes
@figentra/<product>-docs: the MDX pages ofdocs/plus their navigation. It goes to our own registry (0453), never to npmjs. - The API reference is generated. It comes from the
openapi.jsonalready inside the product’s contract packages,@figentra/<service-package>-contract(0511). Nobody writes API reference pages by hand. - One hub at docs.figentra.com. The hub is a new app member of the Figentra platform repository (figentra/figentra),
shaped like the member behind docs.stackra.figentra.com (
stackra.kindpackage, tierapp), and its root runway sends it to thedocsdestination oncloudflare-workers. It depends on every product docs package through its catalog. Its product switcher has one tab per product: os, pay, billing, invoicing, commerce, tamo, organza and each product that follows. - A release rebuilds the hub through one bump pull request. A product release opens the hub’s bump pull request in figentra/figentra, or updates it in place when one is open, moving that product’s catalog pin. Its per-pull-request preview shows the new docs before merge. When it merges, the hub’s normal deploy on main rebuilds it and Runway deploys it. Main is the only source of what is deployed: the hub never builds a version that is not in its lockfile, and a release never dispatches another repository’s deploy.
- Packages, not a cross-repository checkout. The hub reads released packages, so its docs match the released code, and it needs no read access to the private product repositories.
- Stackra and Flow keep their own sites. Their readers are different. Stackra’s stays at docs.stackra.figentra.com, and Flow’s is open source. Both move to Fumadocs under decisions 1 to 3, and either can become a hub tab later.
- A docs package has its own kind,
docs. The repository-rootdocs/is the member@figentra/<product>-docs, and itspackage.jsoncarries"stackra": { "kind": "docs" }. Itscontent/holds the MDX pages, a Fumadocsmeta.jsonper folder for the navigation, and the assets those pages use; beside it sit only the member files (package.json, README, AGENTS, CHANGELOG): no code, no tier, no TypeScript or Vitest preset.stackra.kindgets a seventh value,docs, as 0511 addedcontract(amending decision 11 of 0453). A content-only package takes this kind; an app that serves docs, like the hub, stays apackageof tierapp. New pages use Fumadocs components directly. The Mintlify component names already in the pages (Note,Warning,Tip,Card,CardGroup,Tabs,Steps) are mapped onto Fumadocs components by the sites as a transitional bridge for the migration, removed once no published docs package uses them.
Consequences
- Mintlify leaves every repository: the
minttasks, themintlifyRunway provider, the deploy branches, the Mintlify GitHub app and the “Mintlify Deployment” checks. Gen’s docs-site target (the 2026-10-27 note on 0002) stops writing a Mintlify site. Core’s own pages move fromapps/docs/src/docstodocs/, and the tools that name the old path (pnpm adr:reserve, the ADR links) move with them in the same pull request. - The checks of 0299 stay, run on the Fumadocs build: the build, broken links, accessibility, and a smoke test after each deploy.
- Each product’s Release grows one package, and its CI builds the docs on every pull request that touches
docs/. - The hub is one more member, deployed like any Worker; its content changes only when a bump pull request merges. The bump pull requests are routine: they take Flow’s bot-approval path once it is live, and until then they go in the owner’s merge batch.
- Rolling back a product’s docs is rolling back its docs package version in the hub.
Enforcement
planned —StackraKind.Docs in STACKRA_MANIFEST_SCHEMA (packages/developer/repo-checks), released before any
product docs package; the Runway Cloudflare Workers provider (STA-1921, stackra#227) as the only deploy path; the hub member and its
release’s bump pull request; one migration pull request per repository under STA-1920 that adds docs/, adds the docs package to
the Release, moves the Mintlify content and removes Mintlify and its checks; a FORBIDDEN_DEPENDENCIES row for mint
and mintlify in @stackra/repo-checks once the last repository has moved. Until then nothing checks this rule.