| name | book-writer |
| description | Patterns for writing technical book chapters in Markdown with Mermaid diagrams, served via ProperDocs (a MkDocs fork). Use this skill whenever writing, editing, reviewing, adding, removing, or renaming book chapters, organizing multi-chapter content, fixing Mermaid rendering issues, or changing the book's structure. Also triggers when updating properdocs.yml, docs/ symlinks, or navigation — even if the user just says "add a chapter" or "reorganize sections" without mentioning MkDocs. |
| metadata | {"last-updated":"2026-05-25"} |
Book Writer
Write source-code-referenced technical books in Markdown with Mermaid diagrams, served as a ProperDocs website. Covers chapter structure, content flow, diagram syntax, and keeping the ProperDocs site in sync with content changes.
ProperDocs Site Maintenance
The book is served via ProperDocs with the Material theme. When chapter content changes, the site configuration must stay in sync. Forgetting this breaks navigation or hides new chapters from readers.
When you add a new chapter
- Create
NN-slug.md with the chapter template below
- Add a nav entry to
properdocs.yml in the correct Part section:
- "N. Chapter Title": NN-slug.md
- Create a symlink in
docs/:
ln -sf "../NN-slug.md" "docs/NN-slug.md"
- If the chapter number changes existing chapters, renumber the affected
properdocs.yml entries too
When you remove a chapter
- Delete the
.md file
- Remove its entry from
properdocs.yml nav
- Remove the symlink from
docs/
- Renumber subsequent chapters if needed (in filenames,
properdocs.yml, and section headings inside the files)
When you rename or reorder chapters
- Rename the
.md file
- Update the
properdocs.yml nav entry (both the label and the filename)
- Update the
docs/ symlink
- Update all
## N.x section headings inside the file to match the new chapter number
properdocs.yml nav structure
The nav groups chapters into Parts. Each Part is a collapsible section in the sidebar:
nav:
- Introduction: index.md
- "Part I: Getting Started":
- "Frontmatter": 00-frontmatter.md
- "1. Introduction": 01-introduction.md
- "Part II: Kernel & Boot":
- "4. Boot and Init": 04-boot-and-init.md
The label format is "N. Short Title": NN-slug.md. Keep labels short — they appear in the sidebar.
docs/ symlinks
ProperDocs reads from docs/ which contains symlinks to the actual chapter files in the repo root. This indirection exists because ProperDocs requires docs_dir to be a child directory, but chapters live at the repo root for simplicity.
When creating symlinks, always use relative paths (../filename.md) so they work regardless of absolute path. Also symlink any static assets the chapters reference.
Chapter Structure
Use this template for every chapter:
# Chapter N: Title
> *Optional opening quote*
Introduction paragraph (no heading).
---
## N.1 First Major Section
### N.1.1 Subsection
## N.X Try It
Hands-on exercises with real commands.
## Summary
Key takeaways as bullets.
### Key Source Files
| File | Purpose |
Example:
# Chapter 5: CPU Acceleration
The emulator runs guest code at near-native speed by handing the virtual CPU to
a host hypervisor, falling back to TCG binary translation only when none is...
---
## 5.1 Why Acceleration Matters
### 5.1.1 The TCG Fallback
## 5.7 Try It
- Run `emulator -accel-check` to see which accelerator is available on your host
## Summary
- KVM, Hypervisor.framework, WHPX, and AEHD each back the same accelerator interface
Content Guidelines
Reference real source code. Every architectural claim should point to a specific file and line — this is what makes the book valuable beyond a generic overview.
static int _console_client_init(ControlClient client) {
...
}
Match code block language to source file extension. The emulator tree is mostly C++ (.cpp/.h) and C (.c), with Python build/test scripts, some Go (tools/netsim), and Java/Kotlin in host-side tooling. Use ```cpp, ```c, ```python, ```go to match the file — never mislabel. Key tells: C++ uses ::, std::, class; Go uses :=, func (c *config), no semicolons; Python uses def, : blocks, no braces.
def run(self) -> None:
...
Use manual section numbers matching the chapter (## 5.1 for chapter 5). ProperDocs doesn't auto-number, and if you ever generate PDF, Pandoc's auto-numbering doubles manual numbers.
Title format: # Chapter N: Title with colon separator. Not --, not — (em-dash) — those slip in from autocomplete and routine editing and have to be fixed in audit passes.
End every chapter with "Try It" (hands-on exercises) immediately followed by "Summary" (key takeaways). Summary is the last ## section, full stop. Don't append more sections after Summary — not "Appendix", not "Deep Dive", not a new feature you forgot about. If you have extra material, fold it into a numbered section before Try It, or extract it into the standalone appendix file. Reviewers found this drift in 5+ chapters during a single audit pass; it always starts as "just one more section" and degrades the chapter shape.
Watch for duplicate section numbers when inserting new content. Adding a new ## 9.10 between existing sections requires renumbering everything that follows — or you end up with two ## 9.11 headings later in the chapter (real bug found in chapter 9). Skim the full heading sequence after any insertion.
Content Organization
Bottom-to-top for system books — each layer builds on the one below:
Build system → QEMU machine & CPU acceleration → virtual hardware → android-emu core (sensors, snapshots, control plane) → graphics pipeline → media → connectivity → UI & streaming → guest integration → infrastructure (testing, debugging)
Mermaid Diagrams
Caption every mermaid block with an italic line directly after its closing fence: *Figure N-M: Description*, where N is the chapter number and M is the diagram's 1-based position within the chapter. Do not put ### Diagram: or #### Figure headings above diagrams — the caption below is the only label. When inserting or removing a diagram, renumber the later captions in that chapter.
For syntax rules (quoting, special characters, parse errors), read references/mermaid-syntax.md. The short version: quote any node label containing (), <br/>, or |.
Visually verify every mermaid edit
Parse-clean is not enough. Mermaid will happily render a diagram with text overflowing its rectangle, nodes overlapping, or arrows crossing into illegibility — and it will also render diagrams that are syntactically valid but factually wrong about the architecture (missing components, reversed arrow direction, made-up relationships). The build pipeline doesn't catch any of that.
After writing or editing any mermaid block, render it to PNG and look at the result:
./serve.sh png NN-slug.md
./serve.sh png --all
PNGs land in .mermaid-png/<slug>/NN-<sha16>.png (one file per block, indexed in chapter order). The wrapper runs tools/render_mermaid_png.py inside the book-serve Docker image, reusing the same Playwright + Chromium that the SVG cache already uses. PNGs are content-addressed by the same hash as the SVG cache, so reruns skip unchanged diagrams.
The script also refreshes .mermaid-cache/<sha16>.svg for any block whose hash isn't there yet — that's the same cache the pdf/epub plugins read, so editing a diagram and running ./serve.sh png leaves the next serve.sh pdf or serve.sh epub build with full cache hits and no Mermaid re-render. One command keeps both caches in sync.
What to check on each PNG:
- Layout. Every label sits inside its shape. No text spills past a rectangle's edge. No two nodes or edge labels overlap. Long labels use
<br/> breaks (in quoted node labels — never in transition labels).
- Architectural accuracy. Open the chapter alongside the PNG. Every box in the diagram corresponds to a component the prose actually mentions. Arrow direction matches the described data/control flow. Subgraph groupings reflect the real process / package boundaries (e.g.
system_server boxes only contain things that live in system_server). No invented relationships.
- Readability at zoom-1. Open the PNG at native size — if you have to squint, the diagram has too many nodes and should be split.
Don't ship a chapter without re-rendering the diagrams you touched.
Parallel Writing
For 20+ chapters, launch 5 agents per batch. Review after each batch — then update properdocs.yml nav and docs/ symlinks for all new chapters before starting the next batch.
Lists
Markdown lists silently break when you forget the blank line before them — they render as inline text instead of a proper list. This is the single most common formatting issue in the book (we fixed 1,268 instances).
Always leave a blank line before any numbered or bullet list:
BAD — renders on one line:
Services are started in four phases:
1. Bootstrap services
2. Core services
GOOD — renders as proper list:
Services are started in four phases:
1. Bootstrap services
2. Core services
Match counts to list items. If you write "three phases:" make sure exactly three items follow. Readers notice when the prose says "three" but the list has four items — it undermines trust in the technical accuracy of the entire chapter.
Quick Reference
| Do | Don't | Why |
|---|
| Blank line before every list | List right after text | Renders inline instead of as a list |
| "four phases:" with 4 items | "three phases:" with 4 items | Count mismatch erodes reader trust |
Update properdocs.yml when adding/removing chapters | Add a chapter file without a nav entry | Readers won't find it in the sidebar |
Create docs/ symlink for every new chapter | Forget the symlink | ProperDocs can't serve files outside docs/ |
## 5.1 Title in chapter 5 | ## 3.1 Title (wrong chapter) | Readers use the number to locate content |
# Chapter 5: Title | # Chapter 5 -- Title or # Chapter 5 — Title | Pick :, stick with it (em-dash creeps in from autocomplete) |
Summary as the last ## section | Any section after ## Summary | Readers stop at Summary; trailing sections get lost |
*Figure N-M: Description* after each mermaid block | ### Diagram: heading above the block, or no caption | Captions sit under the figure; headings above clutter the TOC |
```go for .go files | ```java for Go code | Wrong syntax highlighting, misleads readers |
NODE["text(stuff)"] | NODE[text(stuff)] | Unquoted parens break Mermaid parser |
Idle --> Running : start | Idle --> Running : start() | Parens in stateDiagram-v2 transition labels are a hard parse error — strip them, don't quote |
subgraph HS["Home Screen"] | subgraph Home Screen | Multi-word subgraph names need explicit IDs |
<br/> in stateDiagram/sequenceDiagram labels | \n in stateDiagram/sequenceDiagram labels |