# Book Writer

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

- Skill: `aospbooks/book-writer-2` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add aospbooks/book-writer-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aospbooks/book-writer-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: aospbooks (https://skillmd.com/u/aospbooks)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/aospbooks/book-writer-2

---


# 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

1. Create `NN-slug.md` with the chapter template below
2. Add a nav entry to `properdocs.yml` in the correct Part section:
   ```yaml
   - "N. Chapter Title": NN-slug.md
   ```
3. Create a symlink in `docs/`:
   ```bash
   ln -sf "../NN-slug.md" "docs/NN-slug.md"
   ```
4. If the chapter number changes existing chapters, renumber the affected `properdocs.yml` entries too

### When you remove a chapter

1. Delete the `.md` file
2. Remove its entry from `properdocs.yml` nav
3. Remove the symlink from `docs/`
4. Renumber subsequent chapters if needed (in filenames, `properdocs.yml`, and section headings inside the files)

### When you rename or reorder chapters

1. Rename the `.md` file
2. Update the `properdocs.yml` nav entry (both the label and the filename)
3. Update the `docs/` symlink
4. 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:

```yaml
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:

```markdown
# 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:**
```markdown
# 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.

```cpp
// Source: external/qemu/android/android-emu/android/console.cpp
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.

```python
# Source: external/qemu/android/build/python/aemu/tasks/build_task.py
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:

```bash
./serve.sh png NN-slug.md          # one chapter
./serve.sh png --all               # every chapter (slow)
```

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:

1. **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).
2. **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.
3. **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:**

```markdown
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 | `\n` renders literally in those contexts (silently); flowchart labels are the exception |
| `{placeholder}` in flowchart labels | `<placeholder>` in flowchart labels | SVG renderer strips angle-bracket placeholders as HTML tags — text vanishes silently |
| Source path + line number | "The framework does X" | Unverifiable claims undermine the book |

