A runtime-rendered app under hash routes is invisible to AI crawlers and one page to Google — the structural weakness of the whole category. ApiGlow answers it twice: every route announces itself while the app runs, and apiglow bake writes the static HTML and Markdown mirror that search engines and agents fetch without running a line of JavaScript.
docs.example.com/op/addPet.html · baked
REAL SCREENSHOT, SHOWN AT 1:1
01
Every route announces itself.
From the first install, with zero configuration, the app manages the document head on every route change: a per-route <title> (“addPet — Petstore”), a meta description derived from the route’s own content, and a JSON-LD block per page — APIReference on endpoints, TechArticle on guides and scenarios, WebSite on the home view. Views no type honestly fits emit none: a wrong type is worse than silence.
02
One command writes the crawler's copy.
AI crawlers run no JavaScript, and Google reads every #/… route as one URL. apiglow bake — a companion CLI inside the same npm package — reads the exact config your host page inlines and writes what the crawlers need: an HTML snapshot and a Markdown mirror per operation, guide and scenario, a sitemap.xml, and llms.txt / llms-full.txt as served files. Deploy the tree next to the app page; the reader’s install stays one script tag.
Each snapshot is real static content: canonical to itself, an alternate link to its Markdown twin, JSON-LD, zero scripts — and one prominent link back into the interactive app. No redirect, no hydration, no user-agent sniffing. It is not a prerender and not static-site generation: it is the app’s export layer written to disk, fed by the same generators as the in-app “Copy page”, so the mirror cannot drift from the product.
04
Agents get files they can fetch.
Baked, llms.txt follows the llmstxt.org convention and links the served Markdown mirrors; every section of llms-full.txt carries a Source: line to its page; and each scenario publishes its Arazzo recipe — the same file a CI runner executes unchanged. The in-browser generation of the AI surface keeps working without a bake; the bake is what turns those downloads into URLs.
05
Or stay out of the index entirely.
Internal documentation opts out with one key: seo: { index: false } injects a noindex robots meta before first paint. The config states its own limit — it is a request to well-behaved crawlers, not a protection; docs that must not be read need an auth wall. And the bake refuses to run on a noindex config: publishing a mirror of a page that asks not to be found is a contradiction it treats as a hard error.
06
The mirror degrades where Node has no DOM.
The bake runs in Node (≥ 24), so raw HTML inside Markdown prose is escaped rather than rendered in snapshots, and a docs page carried by a host-page element (contentId) cannot be baked at all — it is named in the warnings and dropped from the sitemap rather than linked dead. The sitemap carries no <lastmod>, and robots.txt stays yours. Re-run the bake when the schema or the prose changes — in practice, from the CI job that already deploys the site.