Doku-Strategie (`docs.kumiko.so`)
Status: Plan v1, 2026-05-01
Vorgänger: keiner — erste explizite Doku-Strategie
Verknüpft mit: marketing/roadmap.md (Pfad C, L), architecture/observability.md
Strategischer Kontext
Roadmap-Reset: AI-Plattform-First. Free/Pro-Kunden bauen Apps via AI-Builder
auf kumiko.so, sehen NIE direkt Code. Self-Hosted/Code-Access ist Enterprise-
Add-on.
Heißt für Doku: Audience ist primär nicht der Free-User (der redet mit AI), sondern:
| Audience | Wann | Warum |
|---|---|---|
| AI-Builder (LLM) | sofort | braucht Pattern-Reference + Reasons als Knowledge-Base |
| Marc / interne Entwicklung | sofort | Onboarding für sich selbst in 6 Monaten |
| End-User der gehosteten Apps | sofort | Error-Self-Service (Default-Renderer zeigt “Mehr erfahren →“) |
| Enterprise-Kunde mit Code-Access | bei erstem Pilot | komplette Reference + Architecture |
| OSS-Community | später, wenn Open-Sourced | komplett |
Konsequenzen:
- Polish, Marketing-Optik, Search-Bar — erstmal egal
- Auto-Generated ist Pflicht (kein Pflegeaufwand für Marc)
- Vollständig (Enterprise-tauglich) > schön
- Mehrsprachig de + en (DACH-Apps haben deutsche End-User, internationale Kunden haben englische)
Domain + Hosting
Domain: docs.kumiko.so als Sub-Domain. Brand-Trennung zu kumiko.so
(Marketing/SaaS) bleibt logisch erhalten — Doku ist Teil der Plattform-Marke,
keine eigene Dev-Brand.
Auth: keine. Komplett öffentlich. Begründung: alles auto-generated, nichts geheim. Suchmaschinen indexieren, AI-Bots können finden, GitHub-Issues können verlinken.
Hosting auf eigenem K3s (Operators-Stack 38b62679 ist live):
docs.kumiko.so ↓ ingress-nginx (operators-stack) ↓ cert-manager (Let's Encrypt, automatisch)Service: docs-static ↓nginx-Container mit /usr/share/nginx/html = Astro-Build-OutputPulumi-Resource im Operators-Stack definiert:
Deployment: nginx mit Astro-Build als Volume oder Init-Container der aus Container-Registry ziehtService: ClusterIPIngress:docs.kumiko.so→ Service, mit cert-manager-AnnotationCertificate: Let’s Encrypt via cert-manager, Standard-Pattern
Deployment-Pipeline:
- CI baut Docker-Image:
astro build→nginx:alpinemitdist/alsCOPY→ push nach Registry (GHCR oder eigene) - Pulumi update setzt neue Image-Tag → K3s rolling-update
- Trigger: jeder Push auf
mainderapps/docs/oder Auto-Gen-Sources ändert
Tech-Stack
- Astro Starlight für Static-Site
- MD-first, Search via Pagefind built-in, schnell, OSS, kein Vendor-Lock
- Layout-Anpassung minimal (Default-Theme reicht für Phase 1)
- TypeDoc +
typedoc-plugin-markdownfür API-Reference - Custom ts-morph Generators für Patterns + Reasons (ts-morph ist eh im Stack durch C1-C3)
- i18next-YAML-Bundles für Übersetzungen (konsistent mit Framework-i18n)
Auto-Generation aus 5 Sources
| Source | Output-Section in docs.kumiko.so | Tool |
|---|---|---|
packages/framework/src/errors/reasons.ts + tsdoc + i18n-YAMLs | /errors/<reason> | Custom-Generator (ts-morph) |
packages/framework/src/engine/feature-ast/patterns.ts + Builder-tsdoc | /patterns/<kind> | Custom-Generator (ts-morph) |
packages/framework/src/**/*.ts mit @public-tsdoc | /api/* | TypeDoc → markdown-Plugin |
samples/**/README.md | /samples/<name> | MD-Copy + Frontmatter-Injection |
docs/plans/architecture/*.md | /architecture/<topic> | MD-Copy |
NICHT auto-generated (handgeschrieben, später):
- Conceptual Guides (“So baut man Multi-Tenant”, “Soft-Delete-Pattern”) — kommen erst bei Enterprise-Bedarf
- Tutorials — Sample-READMEs sind Tutorials genug für Phase 1
- Marketing-Pages — gehören nach
kumiko.so, nicht in Doku
Build-Pipeline
yarn kumiko docgen → ts-morph durchläuft reasons.ts, patterns.ts, builder-files → schreibt nach apps/docs/content/{errors,patterns,api,samples,architecture}/ → samples/*/README.md werden 1:1 kopiert mit Frontmatter → docs/plans/architecture/*.md dittoyarn workspace docs build → astro build → static HTML in apps/docs/dist/CI-Hook:
- Push auf
mainmit Diff in Auto-Gen-Sources oderapps/docs/→kumiko docgenläuft → Image-Build → Pulumi-Update → Live
i18n-Layout für Errors
Trennung: Code (TS) trägt nur Struktur und Metadaten. Texte (für End-User und Developer) liegen in YAML-Bundles, sprachgetrennt.
packages/framework/src/errors/reasons.ts:
export const FrameworkReasons = { /** * Triggers when atomic UPDATE lost the optimistic-locking race. * Client SDK default: toast + re-fetch. * * @httpStatus 409 * @sdkBehavior toast-and-refetch */ staleState: "stale_state",} as const;packages/framework/src/errors/i18n/de.yaml:
stale_state: endUser: | Jemand anderes hat dieses Element zwischenzeitlich geändert. Bitte Seite neu laden und nochmal speichern. developer: | ConflictError beim Optimistic-Locking-Race. Ein anderer Writer hat die Row zwischen Snapshot und WHERE-Clause bewegt.packages/framework/src/errors/i18n/en.yaml:
stale_state: endUser: | Someone else modified this item in the meantime. Please reload the page and try saving again. developer: | ConflictError fires when an atomic UPDATE lost the optimistic- locking race — another writer moved the row between our snapshot and our WHERE clause.Workflow: Marc schreibt de.yaml (Tone, Idiomatik). kumiko docgen --fill-missing-translations ruft Anthropic über @kumiko/ai-foundation auf,
generiert en.yaml für fehlende Keys, Marc reviewt grob.
Drei-fach-Konsument, eine Source pro Sprache:
reasons.ts (codes + metadata)i18n/de.yaml + i18n/en.yaml (texts) │ ├─► docs.kumiko.so/errors/<reason>?lang=de|en (auto-generated MD) ├─► i18next-bundle für Runtime (User sieht Error-UI in seiner Sprache) └─► AI-Bot-Knowledge-Base (System-Prompt-Material in beiden Sprachen)KumikoError mit docsUrl
Erweiterung am bestehenden Shape (packages/framework/src/errors/kumiko-error.ts):
export abstract class KumikoError extends Error { abstract readonly code: string; abstract readonly httpStatus: number; readonly i18nKey: string; readonly i18nParams: Readonly<Record<string, unknown>> | undefined; readonly details: unknown; readonly docsUrl: string; // ← neu, computed aus reason // ...}docsUrl wird automatisch gesetzt aus reason → https://docs.kumiko.so/errors/<reason>.
Konvention, kein Free-Form.
serialize.ts exposed docsUrl in HTTP-Response-JSON. Default-Renderer
(@kumiko/renderer-web und Mobile) zeigt:
- Title (i18next-übersetzt) — prominent
- Body (i18next, kürzer)
- Kleiner Link “Mehr erfahren →” wenn
docsUrlgesetzt
End-User muss nicht klicken. Aber wenn er will, landet er auf
docs.kumiko.so/errors/<reason>#endbenutzer.
Lint-Regeln
In kumiko check:
- Jeder Reason-Wert in
FrameworkReasons(und Feature-spezifischenReasons-Objekten) hat Eintrag in allen vorhandenen i18n-YAMLs - Beide Sprachen haben dieselben Keys (kein verwaister Eintrag)
- Jeder Eintrag hat
endUserUNDdeveloperSection - CI Fail wenn was fehlt
@public-tsdoc-Pflicht: zunächst kein Lint. Auto-generated Doku ohne
tsdoc landet halt mit “TODO: Description” auf der Doku-Seite. Wenn das stört,
später Warning hinzufügen.
Sprint A — Doku-Foundation (~1 Woche)
| Tag | Output |
|---|---|
| 1 | Astro-Skelett apps/docs/ + Pulumi-Resource (Deployment + Service + Ingress + Certificate) → docs.kumiko.so läuft mit Hello-World |
| 2 | kumiko docgen Command-Skelett + Reasons-Generator (ts-morph parsed reasons.ts + zugehörige i18n-YAMLs → MD pro Reason) |
| 3 | Patterns-Generator (ts-morph über patterns.ts + Builder-tsdoc → MD pro Pattern-Kind) |
| 4 | TypeDoc-Integration für API + Samples + Architecture MD-Copy-Pipeline |
| 5 | CI-Hook: Push auf main mit Diff in Sources → Image-Build → Pulumi-Update → Live |
Acceptance: docs.kumiko.so ist online, zeigt Errors + Patterns + API +
Samples + Architecture, deutsch + englisch wo i18n vorhanden, jeder Push
auto-deployt.
Sprint B — Errors mit docsUrl + dual-audience YAMLs (3-5 Tage)
| Tag | Output |
|---|---|
| 1 | docsUrl ans KumikoError-Shape, serialize.ts exposed, Default-Web-Renderer mit “Mehr erfahren →“-Link |
| 2-3 | Audit aller existierenden Reasons im Framework + Bundled-Features. endUser + developer Texte in de.yaml/en.yaml füllen (Marc deutsch, AI englisch via --fill-missing-translations) |
| 4 | Alle Throws im Framework durchgehen, sicherstellen dass jeder typed Reason hat |
| 5 | Lint-Test der jeden KumikoError prüft (hat Reason + i18n-Einträge in beiden Sprachen + beide Sektionen) |
Acceptance: Jede thrown KumikoError hat docsUrl in HTTP-Response, jede
Reason-Page auf docs.kumiko.so existiert mit beiden Sektionen in beiden
Sprachen, kumiko check failt bei Drift.
Spätere Sprints (verlinkt, nicht Teil dieses Plans)
- OTel/Telemetry-Sprint (siehe
observability.md) — kommt nach Doku live - L2 AI-Builder (siehe
marketing/roadmap.mdPfad L) — parallel im Worktreekumiko-l2. Pattern-Reference von Sprint A wird L2-System-Prompt- Material - Conceptual Guides + Tutorials — kommen wenn erster Enterprise-Kunde oder OSS-Launch ansteht
Offene Fragen (für später)
- Versionierung der Doku: erstmal
latestonly, ab 1.0 entscheiden (/v1,/v2?) - Volltext-Search: Pagefind ist in Starlight built-in, reicht für Phase 1. Bei großem Korpus später Algolia DocSearch (kostenlos für OSS) erwägen
- AI-Bot auf der Doku-Seite (“Frag den Doku-Bot”): erst nach L2 sinnvoll, doppelt nutzbar als First-Line-Support
Bezug zu anderen Architektur-Docs
observability.md: OTel-Plan kommt nach Doku livefeature-structure.md: Feature-Translations-Pattern (r.translations(...)) ist Vorlage für Errors-i18n-Layoutnaming-conventions.md: Reason-Codes sind snake_case (Convention bereits etabliert)