Skip to content

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:

AudienceWannWarum
AI-Builder (LLM)sofortbraucht Pattern-Reference + Reasons als Knowledge-Base
Marc / interne EntwicklungsofortOnboarding für sich selbst in 6 Monaten
End-User der gehosteten AppssofortError-Self-Service (Default-Renderer zeigt “Mehr erfahren →“)
Enterprise-Kunde mit Code-Accessbei erstem Pilotkomplette Reference + Architecture
OSS-Communityspäter, wenn Open-Sourcedkomplett

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-Output

Pulumi-Resource im Operators-Stack definiert:

  • Deployment: nginx mit Astro-Build als Volume oder Init-Container der aus Container-Registry zieht
  • Service: ClusterIP
  • Ingress: docs.kumiko.so → Service, mit cert-manager-Annotation
  • Certificate: Let’s Encrypt via cert-manager, Standard-Pattern

Deployment-Pipeline:

  1. CI baut Docker-Image: astro buildnginx:alpine mit dist/ als COPY → push nach Registry (GHCR oder eigene)
  2. Pulumi update setzt neue Image-Tag → K3s rolling-update
  3. Trigger: jeder Push auf main der apps/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-markdown fü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

SourceOutput-Section in docs.kumiko.soTool
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

Terminal window
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 ditto
yarn workspace docs build
astro build static HTML in apps/docs/dist/

CI-Hook:

  • Push auf main mit Diff in Auto-Gen-Sources oder apps/docs/kumiko docgen lä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 reasonhttps://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 docsUrl gesetzt

End-User muss nicht klicken. Aber wenn er will, landet er auf docs.kumiko.so/errors/<reason>#endbenutzer.

Lint-Regeln

In kumiko check:

  1. Jeder Reason-Wert in FrameworkReasons (und Feature-spezifischen Reasons-Objekten) hat Eintrag in allen vorhandenen i18n-YAMLs
  2. Beide Sprachen haben dieselben Keys (kein verwaister Eintrag)
  3. Jeder Eintrag hat endUser UND developer Section
  4. 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)

TagOutput
1Astro-Skelett apps/docs/ + Pulumi-Resource (Deployment + Service + Ingress + Certificate) → docs.kumiko.so läuft mit Hello-World
2kumiko docgen Command-Skelett + Reasons-Generator (ts-morph parsed reasons.ts + zugehörige i18n-YAMLs → MD pro Reason)
3Patterns-Generator (ts-morph über patterns.ts + Builder-tsdoc → MD pro Pattern-Kind)
4TypeDoc-Integration für API + Samples + Architecture MD-Copy-Pipeline
5CI-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)

TagOutput
1docsUrl ans KumikoError-Shape, serialize.ts exposed, Default-Web-Renderer mit “Mehr erfahren →“-Link
2-3Audit 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)
4Alle Throws im Framework durchgehen, sicherstellen dass jeder typed Reason hat
5Lint-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.md Pfad L) — parallel im Worktree kumiko-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 latest only, 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 live
  • feature-structure.md: Feature-Translations-Pattern (r.translations(...)) ist Vorlage für Errors-i18n-Layout
  • naming-conventions.md: Reason-Codes sind snake_case (Convention bereits etabliert)