--- name: docs-writing description: Conventions for writing and maintaining tako documentation pages under website/content/docs/. Page templates (transport / extractor / middleware / plugin / concept / tutorial / guide / reference), the frontmatter schema, meta.json sidebar wiring, RustExample-backed examples, and the audit-script contract. Invoke whenever a new public type ships and needs a docs page, or when fixing rot in an existing page. --- # Docs writing — tako The docs site lives under `website/` (Fumadocs + Next.js + MDX, Bun, deployed to `tako.rust-dd.com`). Content is `website/content/docs/`. Sections with a single page live as a flat `website/content/docs/
.mdx`; sections with multiple pages live as `website/content/docs/
/.mdx` plus a `meta.json` sidebar manifest. Folder-form sections today: `getting-started/`, `concepts/`, `transports/`, `extractors/`, `middleware/`, `tutorials/`, `reference/`. All of them carry an `index.mdx` overview **except `reference/`**, whose `meta.json` lists only `migration-2-1, migration, features, api`. This SKILL is the **per-page authoring contract**. The audit script (`website/scripts/docs-audit.ts`) and the linter (`website/scripts/lint-mdx.ts`) enforce the rules under §2, §4, and §7. When a section page outgrows a single MDX file (≈ 500 lines), promote it to folder-form: create `
/index.mdx` (move the overview content here) plus per-feature `
/.mdx` pages, add a `
/meta.json` sidebar manifest, and remove `
.mdx`. ## 1. Trigger map — which template to use ``` Adding a public … → Page goes … → Template ────────────────────────── ─────────────────────────────── ───────── transport / protocol → transports/.mdx → §3.1 Transport extractor → expand extractors/.mdx → §3.2 Extractor (body / request-meta / auth / cookies) middleware → expand middleware/.mdx → §3.3 Middleware (auth / security / traffic / metrics) plugin (TakoPlugin) → plugins.mdx (or plugins/) → §3.4 Plugin cross-cutting trait/idea → concepts/.mdx → §3.5 Concept end-to-end use case → tutorials/.mdx → §3.6 Tutorial request-handling guide → flat .mdx → §3.7 Guide normative reference → reference/.mdx → §3.8 Reference ``` Crate ownership (drives the `crate:` key and "which page" calls): | Crate | Owns | |----------------------|------------------------------------------------------------| | `tako-rs` | umbrella re-export (`tako::*`) | | `tako-rs-core` | routing, handlers, middleware traits, body/request/response, state, signals, queue, GraphQL/gRPC/OpenAPI helpers | | `tako-rs-extractors` | concrete request extractors | | `tako-rs-server` | HTTP/1.1, HTTP/2, HTTP/3, WebTransport, TLS, raw TCP/UDP/Unix, PROXY, compio variants | | `tako-rs-streams` | WebSocket, SSE, file streaming, static files, raw QUIC | | `tako-rs-plugins` | bundled middleware + plugins | | `tako-rs-macros` | `#[tako::route]` / `#[tako::get]` family | | `tako-rs-server-pt` | thread-per-core entry point | If a new type does not fit an existing section, **stop and ask** — adding a new top-level section is a sidebar decision, not a per-page one. ## 2. Frontmatter schema (mandatory) Every page begins with frontmatter validated by zod in `website/source.config.ts` and re-checked by `website/scripts/lint-mdx.ts`. ```yaml --- title: # required description: # required; comfort window 24-152 category: transport # concept | guide | transport | extractor | middleware | plugin | tutorial | reference subcategory: diffusion # optional, free string crate: tako-rs-server # optional; must match /^tako-rs(-[a-z]+)*$/ module_path: tako::server::serve_h3 # optional since: 2.0.0 # optional; /^\d+\.\d+(\.\d+)?(-[a-z0-9.]+)?$/ status: stable # stable | experimental | deprecated runtime: both # tokio | compio | both — tako's dual-runtime axis features: [http3, tls] # optional; cargo features needed (inline flow array) replaced_by: # REQUIRED when status: deprecated --- ``` Current house convention: every page carries `title`, `description`, `category`, `since: 2.0.0`, `status: stable`. Add `crate`, `runtime`, and `features` on catalog pages (transports / extractors / middleware) where they are meaningful. `description` is the OG meta + search snippet — keep it one sentence, ≤ 152 chars to avoid the soft warning. ## 3. Page templates Each skeleton is modelled on a real page — open the cited page for the full house style before writing a new one. ### 3.1 Transport — base: `transports/http.mdx` ```mdx --- title: HTTP/3 description: … category: transport crate: tako-rs-server runtime: tokio features: [http3] since: 2.0.0 status: stable --- # HTTP/3 ## Serving it ```rust // minimal serve example, real API names from tako-rs-server ``` ## Configuration ## TLS / certificates (if relevant) ## Constraints for tokio-only / feature gates See also: /docs/concepts/runtimes, /docs/transports (catalog). ``` Use a `` split only when the transport ships on both runtimes with different entry points. ### 3.2 Extractor — base: `extractors/body.mdx` Group page (body / request-meta / auth / cookies). One `##` section per extractor: the real type name, what it pulls from the request, a handler snippet, and the feature gate. Put a `` on any security-sensitive extractor (e.g. unverified JWT claims). Cross-link the matching middleware (`/docs/middleware/auth`). ### 3.3 Middleware — base: `middleware/auth.mdx` Group page (auth / security / traffic / metrics). Lead with the middleware model (`.into_middleware()` vs `router.plugin(...)`), then one `##` per middleware: constructor, what it does, ordering notes. Verify the real type names against `tako-rs-plugins` — they differ from the README's friendly names (`Csrf` not `CsrfMiddleware`, `CookieSigned` not `SignedCookieJar`). ### 3.4 Plugin — base: `plugins.mdx` Explain the `TakoPlugin` trait, the `plugins` feature, and the plugin-vs-middleware split (a plugin can `install()` its own routes; middleware only wraps the chain). Link to the four middleware group pages. ### 3.5 Concept — base: `concepts/architecture.mdx` Cross-cutting explanation (architecture, request lifecycle, runtimes, design philosophy). Prose + tables over code. No per-API depth — link out to the catalog pages for that. ### 3.6 Tutorial — base: `tutorials/rest-api.mdx` End-to-end, runnable. Prefer `` over hand-written code. Walk the reader from empty `main` to a working service; link each building block to its reference page. ### 3.7 Guide — base: `routing.mdx` Flat top-level page for a request-handling topic (routing, state, streams, queue, signals, observability, deployment). Task-oriented prose with focused snippets. ### 3.8 Reference — base: `reference/features.mdx` Normative: the cargo feature graph, migration ledger, API index. Tables + exact, exhaustive content. The feature page must cover every flag in the README "Feature Flags" table. ## 4. meta.json sidebar wiring - **Top-level** `content/docs/meta.json` orders the whole sidebar and uses `"---Section title---"` string entries as group separators (e.g. `"---Transports---"`). Folder names (`transports`, `concepts`, …) and flat slugs (`routing`, `state`, …) are listed in display order. - **Folder** `
/meta.json` is `{ "title": "...", "pages": [...] }`. List `index` first when the folder has an overview page. - The audit **fails** if an `.mdx` file is not listed in its folder's `pages` array. Every new page must be added to the relevant `meta.json`. ## 5. MDX components Registered globally in `website/mdx-components.tsx` — no import in MDX. - **`Tabs` / `Tab`** — only for a genuine multi-variant split; the canonical tako case is Tokio vs Compio. A lone snippet is a plain fenced ```rust block, not a one-tab `Tabs`. - **`Callout`** — `…` (`info | warn | error`). Use `warn`/`error` for security gotchas and tokio-only constraints. - **`RustExample`** — `` inlines a real workspace file verbatim. The path is relative to the **repo root** (`/Users/danixx/Desktop/tako`), not `website/`. The file must exist or the audit fails. Internal links are **site paths**, never `.md`: top-level `foo.mdx` → `/docs/foo`; `transports/http.mdx` → `/docs/transports/http`; folder index `transports/index.mdx` → `/docs/transports`. ## 6. Examples must be real Accuracy is the whole job. Read the crate source before writing — do not invent signatures or type names. Prefer `` pointing at a real file in `examples/` over a hand-written snippet. Keep tokio-only vs compio support correct (the README transport matrix is the reference: HTTP/2 + TLS, h2c, HTTP/3, WebTransport, raw TCP/UDP, Unix sockets, and PROXY protocol on both runtimes; only the raw QUIC helper `RawQuicSession` is tokio-only). When a type's friendly name in the README differs from its exported name, document the exported name and mention the catalog name once. ## 7. The audit-script contract Run before every commit that touches docs: ```bash cd website bun run typecheck # tsc --noEmit bun run lint:mdx # frontmatter zod schema (scripts/lint-mdx.ts) bun run audit # lint:mdx + meta coverage + RustExample + link graph bun run build # next build — MDX + zod schema, the source of truth ``` - **`lint:mdx`** hard-fails on: missing `title`/`description`; `description` length outside `[20, 160]`; `category` / `status` / `runtime` outside their enums; `crate` not matching `/^tako-rs(-[a-z]+)*$/`; `status: deprecated` without `replaced_by`. It soft-warns when `description` is outside the `[24, 152]` comfort window. - **`audit`** runs `lint:mdx`, then hard-fails on: an `.mdx` file missing from its directory's `meta.json` `pages`; a `` that does not exist; a broken internal `/docs/...` link. ### New-page checklist 1. Write `content/docs/<…>.mdx` with full frontmatter (§2) and an `# H1` matching `title`. 2. Add its slug to the relevant `meta.json` `pages` array (§4). 3. Ground every example in real source; use `` for runnable files (§6). 4. `bun run audit && bun run build` — both green before committing.