Skip to content

Commit d3cec88

Browse files
therajanmauryaRajan Mauryaclaude
authored
docs: add docs/DEVELOPMENT.md authoring guide (#133)
Canonical guide for writing the KmpToolkit docs/ tree. Covers the three content types specific to this repo (narrative pages, per-module landing pages with/without README embed, cookbook recipes) and the three published surfaces (mkdocs site, Dokka API reference, GitHub Wiki). Cookbook section is the most prescriptive — captures the CI-enforced constraints (≤80 lines, ≥1 kotlin block, frontmatter with reviewed_by date+version) and the recommended structure (Quick start MWE, per-platform caveats, Related links). References `_partials/cookbook-recipe-template.md` as the canonical shape. Module section explains the README-embed vs placeholder duality and the migration rule (when a module gains `cmp-*/README.md`, convert its `docs/modules/cmp-*.md` placeholder in the same PR). Lists the 14 legacy `docs/{module}/` subdirs excluded from the mkdocs build with the explicit rule "don't add new content there — use cmp-*/README.md or docs/cookbook/ instead." Wired into mkdocs nav as Contributing → Docs authoring guide. Co-authored-by: Rajan Maurya <therajanmaurya@Rajans-MacBook-Pro.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent caeec45 commit d3cec88

2 files changed

Lines changed: 271 additions & 0 deletions

File tree

‎docs/DEVELOPMENT.md‎

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
---
2+
title: "Docs authoring guide"
3+
---
4+
5+
# Docs authoring guide
6+
7+
How to write, structure, and ship the documentation that lives under `docs/`.
8+
KmpToolkit has a richer docs surface than a single-module library — this guide
9+
captures the three content types (narrative, cookbook recipes, per-module
10+
pages), the conventions each one follows, and the publishing pipeline that
11+
serves them.
12+
13+
## The three surfaces
14+
15+
| Surface | Source | Lands at |
16+
|---------|--------|----------|
17+
| **mkdocs site** (canonical) | `docs/**`, `mkdocs.yml` | `https://mobilebytelabs.github.io/KmpToolkit/` |
18+
| **Dokka API reference** | Kotlin `///` KDoc in source | Bundled inside each module's `-javadoc.jar` on Maven Central |
19+
| **GitHub Wiki** | `docs/**` mirrored | `https://github.com/MobileByteLabs/KmpToolkit/wiki/<basename>` |
20+
21+
The mkdocs site is the primary product. The Dokka HTML is reference-only and
22+
opens from Maven Central. The wiki is a passive mirror for users who prefer
23+
GitHub's UI.
24+
25+
## The three content types
26+
27+
### 1. Narrative docs (`docs/index.md`, `docs/getting-started.md`)
28+
29+
Top-of-funnel pages. Authored prose, full freedom on structure. Keep these
30+
short — the user is here to find a path into the library, not read a book.
31+
32+
### 2. Per-module pages (`docs/modules/cmp-*.md`)
33+
34+
One page per published module. 21 today, mirroring the 21 `cmp-*` modules
35+
in the source tree. Two flavors:
36+
37+
- **README-embedded** (10 modules with `cmp-*/README.md`): the per-module
38+
page uses the `mkdocs-include-markdown-plugin` Liquid-style directive to
39+
embed the module's source-tree README. See any existing
40+
`docs/modules/cmp-network-monitor.md` for the live syntax. **Don't
41+
duplicate** the README content into the `docs/modules/` page — let the
42+
include do its job.
43+
- **Placeholder** (11 modules without README.md yet): minimal "this module is
44+
shipped; full docs coming" page with a link to the GitHub source.
45+
46+
Whichever flavor: **always** include a one-line note about the API reference
47+
being inside the `-javadoc.jar` on Maven Central.
48+
49+
When a module gains a `cmp-*/README.md`, convert its `docs/modules/cmp-*.md`
50+
placeholder to the embedded form in the same PR.
51+
52+
### 3. Cookbook recipes (`docs/cookbook/{topic}/{recipe}.md`)
53+
54+
The bulk of the user-facing docs. Strict format, CI-enforced. Use the
55+
template at [`_partials/cookbook-recipe-template.md`](_partials/cookbook-recipe-template.md):
56+
57+
```markdown
58+
---
59+
title: "How do I {task}?"
60+
reviewed_by:
61+
date: 2026-06 # YYYY-MM — bumped on review
62+
version: 3.5.x # last verified kmp-toolkit version
63+
---
64+
65+
# How do I {task}?
66+
67+
## Quick start (minimal MWE)
68+
```kotlin
69+
// ≤ 15 lines runnable.
70+
```
71+
72+
## Caveats / per-platform notes
73+
- **Android:** …
74+
- **iOS:** …
75+
76+
## Related
77+
- Module: [cmp-{name}](../../modules/cmp-{name}.md)
78+
- Sample: [`samples/sample-cmp-{name}/.../File.kt`](https://github.com/MobileByteLabs/KmpToolkit/tree/development/samples/sample-cmp-{name})
79+
```
80+
81+
**Hard constraints (CI-checked):**
82+
83+
- ≤ 80 lines total (`wc -l`)
84+
- ≥ 1 ` ```kotlin ` code block (`grep`)
85+
- Frontmatter has `reviewed_by.date` (YYYY-MM) + `version`
86+
- "How do I {task}?" title — phrased as a user question
87+
88+
**Soft conventions:**
89+
90+
- Quick start is ≤ 15 lines of copy-paste-runnable code
91+
- Caveats prefer per-platform bullets over prose
92+
- Related links: module page + sample + (optional) ADR
93+
94+
A new cookbook topic gets its own subdir + an `index.md` topic index that
95+
lists the recipes + the underlying modules. See
96+
[`docs/cookbook/network-monitor/index.md`](cookbook/network-monitor/index.md)
97+
for the shape.
98+
99+
## Files with special meaning
100+
101+
| File | Used by | Purpose |
102+
|------|---------|---------|
103+
| `index.md` | mkdocs | Root URL of the site (`/`). |
104+
| `_partials/cookbook-recipe-template.md` | authors (manual copy) | The canonical recipe shape. Don't edit casually — every recipe inherits. |
105+
| `requirements.txt` | docs-publish workflow | Pinned mkdocs deps. Change a version here, not in the workflow. |
106+
| `stylesheets/mbs-brand.css` | mkdocs | Brand polish. |
107+
108+
The `cmp-*/README.md` and `cmp-*/DEVELOPMENT.md` files at module roots are
109+
**not under docs/** but feed the docs pipeline (paths trigger the
110+
docs-publish workflow on push).
111+
112+
## Excluded legacy directories
113+
114+
These per-module docs subdirs predate the mkdocs site and use relative links
115+
that resolve only in the GitHub UI. They live in `docs/` for backward compat
116+
but are excluded from the mkdocs build via `mkdocs.yml` → `exclude_docs:`:
117+
118+
```
119+
docs/app-intents/ docs/bubble/ docs/clipboard/
120+
docs/firebase-analytics/ docs/in-app-update/ docs/intent-launcher/
121+
docs/inter-app-comms/ docs/network-monitor/ docs/open-url/
122+
docs/pdf-generator/ docs/remote-config/ docs/share/
123+
docs/toast/ docs/user-tickets/ docs/BUBBLE.md
124+
docs/CLIPBOARD_MONITOR.md docs/FEATURE_REQUEST.md
125+
docs/REMOTE_CONFIG.md docs/REMOTE_CONFIG_SAMPLES.md
126+
```
127+
128+
**Don't add new content to those directories.** Either:
129+
130+
- New module-level docs → write a `cmp-*/README.md` (it becomes the source
131+
for `docs/modules/cmp-*.md` via include-markdown)
132+
- New how-to → write a cookbook recipe under `docs/cookbook/{topic}/`
133+
- New narrative → write under `docs/` root + register in `mkdocs.yml` nav
134+
135+
When a legacy directory's content gets migrated to a current surface, drop
136+
its line from `exclude_docs:` in the same PR.
137+
138+
## Adding new content
139+
140+
### A new cookbook recipe
141+
142+
1. Pick the topic subdir (or create one — see "A new cookbook topic" below)
143+
2. Copy `_partials/cookbook-recipe-template.md` → `cookbook/{topic}/{slug}.md`
144+
3. Fill in frontmatter + body (≤80 lines, ≥1 kotlin block)
145+
4. Add the entry to `cookbook/{topic}/index.md`'s recipe list
146+
5. **Don't** add individual recipes to `mkdocs.yml` nav — only the topic
147+
`index.md` is in nav; recipes are reached via the topic index
148+
149+
### A new cookbook topic
150+
151+
1. Create `cookbook/{topic}/index.md` listing the recipes + modules
152+
2. Add the entry to `mkdocs.yml` → `nav: Cookbook:` (one line per topic)
153+
154+
### A new module landing page
155+
156+
When you ship a new `cmp-*` module:
157+
158+
1. Write `cmp-*/README.md` (the source of truth)
159+
2. Create `docs/modules/cmp-{name}.md` with an include-markdown that points
160+
at the README
161+
3. Add the entry to `mkdocs.yml` → `nav: Modules:` (alphabetical insertion)
162+
163+
### A new narrative page
164+
165+
Rare. Authored at `docs/{slug}.md` + registered in `mkdocs.yml` nav.
166+
167+
## Style guide
168+
169+
### Code blocks
170+
171+
Always declare language. mkdocs-material renders Kotlin, Swift, Bash, YAML,
172+
JSON, TOML out of the box.
173+
174+
````markdown
175+
```kotlin
176+
val monitor = createNetworkMonitor()
177+
```
178+
````
179+
180+
Inline `code` for symbols, API names, flag names.
181+
182+
### Per-platform caveats
183+
184+
When behavior varies, structure as bullet list with bold platform name:
185+
186+
```markdown
187+
- **Android:** auto-init via ContentProvider; no manual `init()` needed.
188+
- **iOS:** call `Bundle.main.URLForResource(...)` from `applicationDidFinishLaunching`.
189+
- **JVM Desktop:** prints to `System.out`; ANSI color enabled if TTY.
190+
- **JS / wasmJs:** requires a user gesture on first invocation.
191+
```
192+
193+
### Tables
194+
195+
Use for any comparison with ≥ 3 dimensions. The 21-module index in
196+
[`index.md`](index.md) and the platform-support matrices are good examples.
197+
198+
### Links
199+
200+
- **Internal** (within `docs/`): relative paths. `mkdocs build --strict`
201+
validates these.
202+
- **Cross-repo source** (`workspaces/mbs/...`): downgraded to INFO-level
203+
warning via `mkdocs.yml` → `validation.links.not_found: info`. Expected.
204+
- **External**: full URLs.
205+
- **Maven Central / API reference**: prefer
206+
`https://central.sonatype.com/artifact/io.github.mobilebytelabs/cmp-{name}`
207+
over the Maven URL — better UX.
208+
209+
## Test locally
210+
211+
```bash
212+
pip install -r docs/requirements.txt
213+
mkdocs serve
214+
# open http://127.0.0.1:8000
215+
```
216+
217+
`mkdocs build --strict` is what CI runs. Most common cause of strict
218+
failures: a new `cookbook/{topic}/{recipe}.md` added without an entry in the
219+
topic `index.md`'s recipe list (the relative link from the index breaks).
220+
221+
## Recipe-freshness audit
222+
223+
Every recipe has `reviewed_by.date` + `version` in frontmatter. Once per
224+
release cycle, scan for recipes whose `reviewed_by.version` is more than one
225+
minor behind current and re-verify their code blocks against the current API.
226+
Bump the date + version after each successful re-verification.
227+
228+
(No CI gate on this yet; expected manual cadence is per-release.)
229+
230+
## What NOT to do
231+
232+
- **Don't hand-author `site/`** — that directory is the mkdocs build output.
233+
- **Don't add a new recipe outside the template format** — CI enforces the
234+
shape (line count + kotlin block presence). Use the template even for
235+
small recipes; consistency is the point.
236+
- **Don't write content into a legacy `docs/{module}/` subdir** — those are
237+
excluded from the build. Use `cmp-*/README.md` or `docs/cookbook/` instead.
238+
- **Don't edit the workflow** to change build behavior — the logic lives in
239+
`mbl-actionhub/docs-publish-mkdocs.yml`. Bump the `@vX.Y.Z` pin in
240+
`.github/workflows/docs-publish.yml` to upgrade.
241+
- **Don't author Liquid templating** in markdown (other than the
242+
`include-markdown` plugin's own directive). Liquid-style braces break
243+
rendering if Pages is ever set back to legacy Jekyll.
244+
- **Don't link recipes from `mkdocs.yml` nav directly** — keep nav to topic
245+
indexes only; recipes are reached via the index. Direct nav entries clutter
246+
the tab bar fast (12 recipes × 4 topics = 48 entries).
247+
248+
## When the site breaks
249+
250+
| Symptom | Cause | Fix |
251+
|---------|-------|-----|
252+
| `/` returns 404 | `docs/index.md` missing | Restore it. |
253+
| Build fails: nav references file that doesn't exist | Stale `mkdocs.yml` nav entry | Remove the entry or create the file. |
254+
| Cookbook recipe rejected by CI for length | Recipe > 80 lines | Split into two recipes OR move detail into a linked sample / ADR. |
255+
| Cookbook recipe rejected for missing kotlin block | All code blocks are bash / yaml / etc. | Add at least one ` ```kotlin ` block, even if a 3-line snippet. |
256+
| `mkdocs build --strict` fails on relative link | Cross-repo source link (`workspaces/mbs/...`) | Already downgraded to INFO via `validation.links.not_found: info`. If you're seeing ERROR, check that the link target literally cannot resolve in any way — even GitHub. |
257+
258+
## Pipeline architecture (one-paragraph version)
259+
260+
The mkdocs build + Pages deploy logic lives **once** in
261+
[`mbl-actionhub/docs-publish-mkdocs.yml`](https://github.com/MobileByteLabs/mbl-actionhub/blob/main/.github/workflows/docs-publish-mkdocs.yml).
262+
This repo's `.github/workflows/docs-publish.yml` is a 5-line caller pinned to
263+
a specific version. The wiki sync is a separate workflow
264+
(`sync-docs-to-wiki.yml`) that mirrors `docs/` to the GitHub Wiki via the
265+
`mbl-actionhub-docshub` composite action. The Dokka API reference is built
266+
inside the Maven publish pipeline (per-module `dokkaGeneratePublicationHtml`
267+
task, bundled into `-javadoc.jar` via `vanniktech.mavenPublish`'s
268+
`JavadocJar.Dokka("dokkaGeneratePublicationHtml")` config). All three
269+
pipelines are independent; a failure in one doesn't block the others.

‎mkdocs.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,5 @@ nav:
123123
- Network monitor: cookbook/network-monitor/index.md
124124
- Observability: cookbook/observability/index.md
125125
- Storage: cookbook/storage/index.md
126+
- Contributing:
127+
- Docs authoring guide: DEVELOPMENT.md

0 commit comments

Comments
 (0)