Rules for the documentation site and its pages, apps/docs. The root AGENTS.md holds the definition of done and the rules for the whole repository; commands run from the repository root.
Kaeso's documentation: the Markdown pages in content/ and the static site that shows them at docs.kaeso.app, in English, German and Simplified Chinese. The site looks and works like the console and is drawn only with @logicplanes/kaeso-ui.
- Is: the only home of documentation for people who use, run or integrate Kaeso: getting started, self-hosting, the console, the APIs, concepts and development. The code keeps short
README.mdfiles that link here. - Is not: a design system. Every visible element is a
@logicplanes/kaeso-uicomponent; the site owns composition and behaviour. A missing component or variant is added topackages/ui, in the same pull request when the site needs it. - Is not: a CMS, a server or a place for decisions. Nothing runs but static files.
- Not a place for plans. Roadmaps, to-do lists and open questions go into issues.
corepack enable
pnpm install
pnpm --filter kaeso-docs exec playwright install chromium
pnpm build:packages
pnpm --filter kaeso-docs dev
Node.js 24 (the repository's .node-version) and pnpm 11 (pinned in the root package.json). pnpm --filter kaeso-docs dev serves the site at http://localhost:4480 and reloads as pages are saved; KAESO_DOCS_CONTENT=e2e/fixtures/content pnpm --filter kaeso-docs dev serves the fixture pages instead, and KAESO_DOCS_PORT chooses another port. The site reads the build of packages/ui: run pnpm build:packages again after changing the library.
The root definition of done covers the site. To run its own checks alone, after pnpm build:packages when the libraries changed:
pnpm --filter kaeso-docs check:content
pnpm --filter kaeso-docs diagrams
pnpm --filter kaeso-docs lint
pnpm --filter kaeso-docs typecheck
pnpm --filter kaeso-docs test
pnpm --filter kaeso-docs build
pnpm --filter kaeso-docs licenses:check
pnpm --filter kaeso-docs e2e
check:content checks every page in every language without building; diagrams draws the Mermaid blocks of the pages with Chromium and removes drawings no page uses; lint runs ESLint and then check:content. test runs Vitest with coverage thresholds. build fails on a content problem or a bundle budget (scripts/budget.ts); licenses:check then checks that every package whose code is in the build is MIT, ISC, BSD, 0BSD or Apache-2.0 licensed. e2e runs Playwright, axe included, against a production build of the fixture pages in e2e/fixtures/content. Then look at every page you changed in light and dark, at desktop and phone widths, in English, German and Chinese, and fix what looks wrong.
- Only
@logicplanes/kaeso-uifor anything visible, from the workspace (workspace:*). No other UI library, no CSS of the site's own.classNameholds layout only (margin, width, grid, flex, gap, position); no colours, radii, type sizes, padding, heights, shadows or inline styles.pnpm lintenforces it (eslint/kaeso.js). - Pages are content, not code. Nothing in
content/is executed or rendered as HTML. Raw HTML stays text, links keep only http, https and mailto or point at files incontent/, images come only fromcontent/. Never weaken this to make a page work; change the page. - Links work on GitHub and on the site. Pages link to files (
../console/api-keys.md#create-a-key), never to site addresses. Heading anchors stay GitHub's. - A broken page fails the build with its file: a link, an anchor, an image, a frontmatter field, a page missing in a language. Problems are never only warnings in a build.
- Every page in three languages.
content/en,content/deandcontent/zh-CNhold the same files with the sameorder; a change to an English page changes both translations in the same commit, following the translation rules. The site's own words live insrc/i18n/messages, typed so that a missing translation fails the typecheck. - Pages describe Kaeso as it is. Every statement is checked against the code in this repository (the gateway, kpp and the console); never document a feature that doesn't exist. Examples use Kaeso's own placeholders (
kaeso.example.com,sk-kso-…,owner@example.com), and the current version is always{{version}}, which the build replaces with the rootpackage.json's version. - No real content in tests. The unit tests and the e2e suite use
e2e/fixtures/contentande2e/fixtures/CHANGELOG.md, which read as Kaeso's own data.content/holds only real pages. - The console's look and house rules, everywhere:
- the wordmark alone at the top left, 28px in and 28px down, the sidebar's labels on the same 28px line; the mark only for favicons;
- no decorative icons, icon circles or badge dots; no serif type; no breadcrumbs; no setup checklists;
- no keyboard-shortcut hints (⌘K works, its hint is not shown); no "N results" counters;
- descriptions are one short sentence; every word follows Kaeso's voice: sentence case, plain words, no exclamation points;
- every error is a toast, never a banner or text in the page;
- nothing changes size when its state changes, and nothing shifts after the first paint;
- a focus ring shows for the keyboard only, never after a click.
- Code blocks in pages never contain comments or
$prompts; explain a command in the sentence before it. - Diagrams are Mermaid, drawn by the build. Every diagram of a system, an architecture, a request or data flow, a sequence, a state or a lifecycle is a
```mermaidblock withaccTitleand, in a sentence or two,accDescr, its labels translated like the page; never ASCII or box-drawing art in a code block, never a screenshot or an image of a diagram.check:contentfails on a code block that draws with box-drawing characters or arrows. The build draws them in strict mode into static images, so nothing of them runs in a reader's browser;pnpm --filter kaeso-docs diagramsdraws new and changed diagrams intodiagrams/, which is committed with the page; writing documentation has the rules. - Tests assert on what a person sees, and the content build's tests on what an author writes. The coverage thresholds are in
vitest.config.ts.
Writing documentation is the binding style guide; read it before you write a page. In short:
- Every page earns its place: a named reader, a task, no other page that says the same, more than a paragraph's worth. Otherwise remove or merge it, and change every link to it in the same commit. Numbers only CI acts on stay in the code that enforces them.
- One page type (quick start, guide, concept, reference, troubleshooting) with that type's template. Guides link to the reference; the same table is never on both.
- Voice: address the reader as "you" („Sie“ in German), imperative instructions, active voice, present tense, sentences under 20 words and never over 30, paragraphs of at most four sentences. No filler, marketing, hedging, exclamation points or "we".
- Lead with a runnable example on every API page and app guide, within the first screen. Requests are a code group of consecutive fences with
tab="curl",tab="Python"andtab="TypeScript", in that order, using the official OpenAI and Anthropic SDKs,kaeso.example.com, the key fromKAESO_API_KEYandclaude-haiku-4-5. - Highlighting: bold only for console labels and defined names, code for everything the reader types, no emphasis.
- Callouts:
NOTE,TIP,IMPORTANTorWARNING; at most one per section and three per page, under 50 words. NoCAUTION. - Next steps: quick starts, guides and overviews end with
## Next steps, a list of two to four[Page title](page.md): One sentence.items, shown as link cards. - Length: title at most 6 words, introduction one to three sentences, quick start at most 10 steps, guide or concept at most 1,500 words, headings
##and###only. - Finish with the checklist under before you merge.
| Path | Holds |
|---|---|
content/<language>/ |
The pages. Folders are sidebar groups; a folder's index.md names and places it |
scripts/content/ |
Frontmatter, slugs, compiling a page, one site per language, the changelog page, the translation checks, the Vite plugin, pnpm check:content |
diagrams/ |
The drawn diagrams, a light and a dark SVG per Mermaid block, named by a hash of its source; written by pnpm --filter kaeso-docs diagrams |
redirects.json |
Old addresses of moved or merged pages and the page each now lives on; the build sends readers on from every old address |
scripts/budget.ts |
The bundle budgets pnpm build ends with |
src/markdown/ |
The page format (ast.ts) and its renderer (render.tsx), library components only |
src/page/ |
A page: title, description, content, previous and next, Edit on GitHub, On this page; not found; load error |
src/shell/ |
AppFrame and the sidebar, the search, the language select, links through the router, toasts, the document title |
src/i18n/ |
The three languages, the preference and the site's own words |
src/router.tsx |
One route tree per language; every address loads its page's chunk |
eslint/ |
The layout-only and no-colour lint rules, with tests |
e2e/ |
Playwright suite and its fixture pages in e2e/fixtures/content |