0027 — Docs framework: Diátaxis + Starlight + llms.txt, agent-native hybrid
Status: Accepted
Date: 2026-04-21
Related spec: docs/specs/2026-04-21-docs-framework-design.md (the WHAT + HOW; this ADR is the WHY).
Context
Section titled “Context”The repo already adopted Diátaxis as its doc taxonomy (see docs/README.md) — four quadrants: tutorial, how-to, reference, explanation. Diátaxis solves organization, not delivery: no search, no rendering, no API / schema auto-render, no versioning, no agent-native index, no enforcement of single-source-of-truth beyond the hand-maintained trigger matrix in CLAUDE.md.
Symptoms the current markdown-only setup can’t address:
- Cofounders read a separate Google Drive doc because raw GitHub MD is hostile to non-devs
- API routes drift from
docs/architecture.md— 30 routes in OpenAPI, no auto-rendered reference - Prisma schema (the canonical data model) isn’t surfaced in docs at all
- Claude fetches files one-by-one via
Read; nollms.txt/llms-full.txtsingle-fetch corpus - No link-check / prose-style / spell / markdownlint gates — dead links accumulate
check-docs-updated.shis honor-system; gaps vs the CLAUDE.md trigger matrix are not gate-enforced- Architecture diagrams exist as inline text blocks, not renderable
.mmd/.d2sources
The ten goals locked during the 2026-04-21 brainstorm (see spec §1) need a delivery stack, not a re-design of the taxonomy.
Decision
Section titled “Decision”Adopt a hybrid stack: keep Diátaxis as taxonomy, add Starlight as the renderer, and expose the llms.txt + llms-full.txt standard as the agent-native layer. Stack layers:
| Layer | Pick | Why |
|---|---|---|
| Taxonomy | Diátaxis (unchanged) | Already adopted; solves organization |
| Content store (SSoT) | Raw Markdown in docs/ (unchanged) | Agents + devs read here; Git-native; renderer-agnostic |
| Renderer | Starlight (Astro) in apps/docs/ | Astro = TS on-stack; Pagefind static search; plugin ecosystem for every goal |
| Agent index | llms.txt + llms-full.txt via starlight-llms-txt | Machine-readable corpus; SOTA 2024–2025 standard |
| API reference | NestJS @nestjs/swagger → starlight-openapi | Reuses existing spec; zero duplication |
| DB reference | prisma-markdown + prisma-erd-generator | Schema → MD + Mermaid ERD |
| Hosting | Cloudflare Pages on docs.ideony.is-a.dev | Free tier; same zone as app + api; Zero Trust free tier covers cofounder gating |
| Access control | Cloudflare Zero Trust email allowlist | Free 50 users; no passwords; auditable |
| Diagrams | Mermaid default, D2 phase 2 | Text-sourced, renderable, diffable; no PNG |
| Search | Pagefind (static, client-side) | No Algolia signup; works offline; no API key |
| Quality gates | markdownlint + vale + cspell + lychee + frontmatter Ajv + mermaid-cli | Layered coverage, battle-tested individually |
The renderer shell (apps/docs/) is a view, not a store. Raw MD in docs/ is SSoT. Deleting apps/docs/ any day → docs still work on GitHub.
Alternatives considered
Section titled “Alternatives considered”Option A — Markdown-only, no renderer (current state, extended)
Section titled “Option A — Markdown-only, no renderer (current state, extended)”Add quality gates + llms.txt generator + OpenAPI → MD pipeline, skip the static site entirely.
- Rejected — zero cofounder UX (raw GitHub MD is hostile for non-devs); no search; no versioning path; no rendered diagrams.
- Kept partially: the MD-as-SSoT invariant IS retained in the chosen option; renderer sits on top, not in place of.
Option B-Docusaurus — Meta’s Docusaurus
Section titled “Option B-Docusaurus — Meta’s Docusaurus”React + MDX, best-in-class versioning + i18n, mature plugin ecosystem, Algolia DocSearch built-in (free OSS tier).
- Rejected — heavier React hydration vs Astro islands; Algolia needs application + approval; aesthetics feel dated OOB and theming is CSS-heavy; versioning + i18n are strengths we don’t need for MVP 0 (YAGNI); plugin coverage for
llms.txtand OpenAPI exists but less mature than Starlight’s equivalents as of 2026-04.
Option B-Mintlify — hosted SaaS
Section titled “Option B-Mintlify — hosted SaaS”Best OOB aesthetics, AI-native search, OpenAPI native, near-zero setup.
- Rejected — SaaS lock-in contradicts OSS-first lean (see ADR 0025); past the free tier it’s $150+/mo; proprietary features block portability; self-host path is limited; our cofounder-facing polish is solvable via Starlight theming without the lock-in.
Option B-MkDocs-Material — Python stack
Section titled “Option B-MkDocs-Material — Python stack”Material Design, battle-tested, excellent plugin ecosystem.
- Rejected — off-stack (everything else is TS); adds Python to dev-env setup surface; contributors would need to context-switch for docs edits; federation story with Jooice (also TS) harder.
Option B-VitePress — Vue-based
Section titled “Option B-VitePress — Vue-based”Fast, lightweight, good DX.
- Rejected — Vue off-stack; thinner plugin coverage for
llms.txt+ OpenAPI vs Starlight; less momentum in 2026.
Option B-Nextra — Next.js-based
Section titled “Option B-Nextra — Next.js-based”Tight Next.js integration, good aesthetics, Vercel DX.
- Rejected — Next.js not present anywhere in Ideony stack (Expo + Nest); adding Next just for docs is gratuitous surface.
Option C — Backstage TechDocs / GitBook / ReadMe (opinionated platforms)
Section titled “Option C — Backstage TechDocs / GitBook / ReadMe (opinionated platforms)”Heavy enterprise tools with strong internal-portal story.
- Rejected — overkill for a 2-person team; steep learning curve; cost.
Option D — Hybrid (chosen)
Section titled “Option D — Hybrid (chosen)”Markdown SSoT + Starlight renderer + llms.txt agent layer. See Decision above.
- Chosen — keeps the raw-MD invariant (agents, devs, Git all read the same source); adds rendered view for cofounders and future public docs; agent-native layer via
llms.txt; zero lock-in; free hosting; plugin ecosystem covers every locked goal.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- Cofounders get a fast, searchable, auth-gated site without leaving Cloudflare infra
- Claude + other agents get
/llms.txt+/llms-full.txt+?format=mdraw source URLs → single-fetch context instead of N-fileReadspam - API + schema + env + CLI references auto-regenerate from source → zero drift by construction
- Quality gates catch dead links / banned words / broken examples at pre-commit, not in review
- Diagram-as-code makes architecture reviews diffable
- Federation with Jooice is a future-compatible refactor (
packages/docs-shell/), not a rewrite llms.txtadoption positions us on the 2024–2025 agent-discoverability standard
Negative / costs
Section titled “Negative / costs”- One additional workspace (
apps/docs/) — 8 files of config + Astro dev server - Starlight dep tree adds ~150 MB to
node_modules/on dev boxes docs/_generated/**needs CI to regenerate before every build (Turbo cached, but still a pipeline step)- Quality gates catch more → commits slow marginally; mitigated by
lint-stagedscoping - Cloudflare Access misconfig would expose internal docs → mitigated by start-closed default-deny policy
- Living-examples (goal #9) CI enforcement deferred to Phase 4.5 after 1-week validation → risk window where broken examples could ship
Neutral
Section titled “Neutral”- Diátaxis stays; taxonomy not touched
- CLAUDE.md trigger matrix stays; Phase 5 audits + upgrades it without replacing it
check-docs-updated.shstays; Phase 5 patches gaps
Migration
Section titled “Migration”Eight-phase rollout in docs/specs/2026-04-21-docs-framework-design.md §13. Each phase reversible; stack is not a big-bang cutover. Phase ordering:
- Renderer shell (day 1)
- Agent layer (day 1–2)
- Auto-gen pipelines (day 2–3)
- Quality gates local (day 3)
- Zero-drift gate audit + upgrade (day 3–4, parallel with 6)
- Diagram migration (day 4, parallel with 5)
- Cofounder migration (day 5+, async, dual-run with Drive)
- Federation prep (post-Jooice docs stand-up)
Phase 4.5 (living-examples CI block) gated on Phase 4 running clean ≥ 1 week.
Revisit trigger
Section titled “Revisit trigger”- Starlight becomes abandonware or a major regression ships → swap to Docusaurus (raw MD stays, renderer changes)
llms.txtstandard stalls → keepllms-full.txt(still useful as flat corpus), dropllms.txtcuration- Pagefind insufficient for scale → add Kapa.ai / Inkeep for semantic search (Phase 2+, out-of-scope here)
- Cloudflare Access free tier exhausted (>50 cofounder+team users) → upgrade to CF Access paid or swap to Netlify Identity / Vercel Password Protection