Task
Generate or update a printable build guide for the project at $1 (relative
path under packages/<domain>/). The guide is a Typst document plus a rendered
PDF, written to <project-path>/docs/build-guide.{typ,pdf}, aimed at someone
assembling and flashing the hardware from scratch.
It differs from the other doc skills by audience and format:
wiring-doc → WIRING.md: terse pin reference for developers.
project-readme → README.md: quick-start for the repo.
build-guide → docs/build-guide.pdf: an at-the-bench, print-ready guide
that pulls BOM + wiring + power + assembly + flash + checkout into one styled
document.
Process
Read the project sources to gather everything the guide needs. Prefer
authoritative sources over prose:
main/pin_config.h (or main/*.h) — authoritative GPIO / bus /
channel assignments. Pin numbers come from here, not the README.
WIRING.md — existing wiring tables, I²C topology, power diagram.
README.md, CLAUDE.md — purpose, architecture, provisioning, OTA notes.
sdkconfig.defaults — target chip, PSRAM/flash size, brown-out, mDNS,
stack sizes, console. Surface any load-bearing settings in troubleshooting.
justfile — real build / flash / monitor recipe names and flash offsets.
partitions.csv — flash layout / OTA partitions and offsets.
main/CMakeLists.txt — REQUIRES reveals components (camera, mdns, ota…).
- Any schematic image under
docs/schematics/images/<name>.png — embed it.
Identify the board and its constraints (PSRAM mode, 3.3 V-only GPIOs,
native USB-Serial-JTAG vs external adapter, GPIO budget, strapping pins).
Write <project-path>/docs/build-guide.typ using the shared template
(see below). Fill each section from real project data; omit sections the
project doesn't use rather than padding with placeholders.
Compile the PDF and link both files from the README (see Compiling
and Wiring up sections).
Using the shared template
Styling and helpers live in tools/typst/build-guide.typ so all guides look
consistent and improve together. Import it and drive the document with
#show: guide.with(...):
#import "../../../../tools/typst/build-guide.typ": guide, callout, htable, theme
#show: guide.with(
title: "<project-name>",
subtitle: "<one-line what it is>",
intro: [ short paragraph for the title page ],
meta: (
("Target MCU", [ESP32-S3 (8 MB PSRAM / flash)]),
("Toolchain", [ESP-IDF v5.4 (containerized)]),
),
difficulty: [Intermediate · \~2–3 h],
header-right: "<board name>",
footer-note: [ Pin data mirrors `main/pin_config.h`, which is authoritative. ],
)
= 1 · Overview
...
The relative import path assumes the guide lives at
packages/<domain>/<project>/docs/; from there ../../../../tools/typst/...
reaches the template. Adjust ../ depth for other nesting.
Helpers exported by the template:
guide(...) — page/text/heading styling + title page + table of contents.
Applied via #show: guide.with(...).
callout(title, body, kind: "info") — soft left-barred box. kind is one of
info, ok, warn, danger, purple. Override with bar:/fill: colors.
htable(cols, header, ..rows, aligns: none) — accent-header, zebra-body
table. header and each row are arrays of content cells.
theme — the color dictionary (theme.accent, theme.muted, theme.rule…).
Do not re-declare page setup, fonts, heading styles, or table colors in the
project file — inherit them from the template so a future style change is a
one-file edit.
Section structure
Use numbered level-1 headings so the table of contents reads as a build order.
Include a section only when the project uses it:
- Overview — what it is, architecture in 1–2 paragraphs,
callouts for the
headline facts (e.g. core split, "what you get").
- Bill of Materials —
htable of Qty / Component / Notes, then a short
"Tools required" paragraph. Flag voltage gotchas with a warn callout.
- System Architecture — embed the schematic via
#figure(image(...));
explain the bus/topology in prose.
- Wiring Reference — subsections of
htables derived from pin_config.h:
GPIO map, I²C topology, PWM/expander channel map, sensor pinouts.
- Power — rails, source, and a
danger callout for the common-ground rule.
- Assembly Steps — an ordered
+ list, power-first, ending with a
pre-power-up continuity check.
- Build & Flash — real
just <module>::* recipes in a code block, flash
offsets table (from justfile / partitions.csv), download-mode warn callout.
- First Boot & Provisioning — WiFi provisioning (Improv/creds), mDNS
hostname, AI backend, OTA.
- Functional Checkout — an
htable of tick-box (☐) checks vs expected
results, ordered to match assembly.
- Troubleshooting —
htable of Symptom / cause & fix, seeded from the
board's known failure modes and load-bearing sdkconfig settings.
End with a small muted footer line pointing at the authoritative sources
(pin_config.h, any ADR) and the regenerate command.
Compiling
Typst is not part of the container toolchain. If typst is missing, install the
CLI from crates.io (GitHub release binaries are blocked by the egress proxy):
CARGO_HTTP_CAINFO=/root/.ccr/ca-bundle.crt cargo install typst-cli --locked
Compile from the guide's directory with the repo root as the sandbox root so
the template import and shared schematic image resolve (both live outside the
project dir). Use the canonical flags — the build-guide-check.yml CI guard
recompiles every guide and fails if the committed PDF differs byte-for-byte, so
the PDF must be produced deterministically:
cd packages/<domain>/<project>/docs
typst compile --creation-timestamp 0 --ignore-system-fonts --root ../../../.. build-guide.typ
--creation-timestamp 0 pins the embedded PDF timestamp; without it the file
carries wall-clock time and never reproduces.
--ignore-system-fonts embeds only Typst's bundled fonts, so glyph fallbacks
are identical on every machine (otherwise Linux FreeSans vs macOS SF diverge).
- Match the Typst version the guard pins (see
TYPST_VERSION in
.github/workflows/build-guide-check.yml); a different compiler release
produces different bytes. Install it with
cargo install typst-cli --version <that-version> --locked.
Verify by rendering a page or two to PNG (--pages 1,3) and eyeballing the
layout before committing.
Commit both build-guide.typ and build-guide.pdf — the PDF is the
deliverable and lets people use the guide without installing Typst.
Wiring up the README
Add a short "Printable build guide" section to the project README.md linking
docs/build-guide.typ and docs/build-guide.pdf, plus the regenerate command.
Style rules
- Authoritative pins — every pin, address, channel, and offset comes from
source (
pin_config.h, partitions.csv, justfile). If source and prose
disagree, trust source and flag it.
- Fill, don't pad — omit sections the project doesn't use. A tight 6-page
guide beats a padded 12-page one.
- One style, one file — never copy the template's styling into the project
guide; import it. Improvements go in
tools/typst/build-guide.typ.
- Callouts for hazards — voltage mismatches, common-ground, PSRAM mode,
download-mode go in
warn/danger callouts, not buried in prose.
- Keep meta honest — read
sdkconfig.defaults and the justfile for the meta
box; don't invent toolchain versions.
- Never print the firmware version — the template's
version: parameter
exists but must stay unset, and nothing generated into docs/auto/ may read
version.txt. release-please bumps version.txt without touching any of the
drift guard's trigger paths, so the committed PDF silently goes stale, and
regenerating it is a docs: commit that mints the next release — a loop that
never converges. Cite version.txt as the source of truth by name if the
guide needs to; never interpolate its contents. See issue #439.
1---2name: build-guide3description: Generate a printable Typst build guide (source + PDF) for an ESP32/MCU project by analyzing its docs, source, and schematic4---56## Task78Generate or update a printable **build guide** for the project at `$1` (relative9path under `packages/<domain>/`). The guide is a Typst document plus a rendered10PDF, written to `<project-path>/docs/build-guide.{typ,pdf}`, aimed at someone11assembling and flashing the hardware from scratch.1213It differs from the other doc skills by audience and format:14- `wiring-doc` → `WIRING.md`: terse pin reference for developers.15- `project-readme` → `README.md`: quick-start for the repo.16- `build-guide` → `docs/build-guide.pdf`: an at-the-bench, print-ready guide17 that pulls BOM + wiring + power + assembly + flash + checkout into one styled18 document.1920## Process21221. **Read the project sources** to gather everything the guide needs. Prefer23 authoritative sources over prose:24 - `main/pin_config.h` (or `main/*.h`) — **authoritative** GPIO / bus /25 channel assignments. Pin numbers come from here, not the README.26 - `WIRING.md` — existing wiring tables, I²C topology, power diagram.27 - `README.md`, `CLAUDE.md` — purpose, architecture, provisioning, OTA notes.28 - `sdkconfig.defaults` — target chip, PSRAM/flash size, brown-out, mDNS,29 stack sizes, console. Surface any load-bearing settings in troubleshooting.30 - `justfile` — real build / flash / monitor recipe names and flash offsets.31 - `partitions.csv` — flash layout / OTA partitions and offsets.32 - `main/CMakeLists.txt` — `REQUIRES` reveals components (camera, mdns, ota…).33 - Any schematic image under `docs/schematics/images/<name>.png` — embed it.34352. **Identify the board** and its constraints (PSRAM mode, 3.3 V-only GPIOs,36 native USB-Serial-JTAG vs external adapter, GPIO budget, strapping pins).37383. **Write `<project-path>/docs/build-guide.typ`** using the shared template39 (see below). Fill each section from real project data; omit sections the40 project doesn't use rather than padding with placeholders.41424. **Compile the PDF** and **link both files from the README** (see Compiling43 and Wiring up sections).4445## Using the shared template4647Styling and helpers live in **`tools/typst/build-guide.typ`** so all guides look48consistent and improve together. Import it and drive the document with49`#show: guide.with(...)`:5051```typst52#import "../../../../tools/typst/build-guide.typ": guide, callout, htable, theme5354#show: guide.with(55 title: "<project-name>",56 subtitle: "<one-line what it is>",57 intro: [ short paragraph for the title page ],58 meta: (59 ("Target MCU", [ESP32-S3 (8 MB PSRAM / flash)]),60 ("Toolchain", [ESP-IDF v5.4 (containerized)]),61 ),62 difficulty: [Intermediate · \~2–3 h],63 header-right: "<board name>",64 footer-note: [ Pin data mirrors `main/pin_config.h`, which is authoritative. ],65)6667= 1 · Overview68...69```7071The relative import path assumes the guide lives at72`packages/<domain>/<project>/docs/`; from there `../../../../tools/typst/...`73reaches the template. Adjust `../` depth for other nesting.7475**Helpers exported by the template:**76- `guide(...)` — page/text/heading styling + title page + table of contents.77 Applied via `#show: guide.with(...)`.78- `callout(title, body, kind: "info")` — soft left-barred box. `kind` is one of79 `info`, `ok`, `warn`, `danger`, `purple`. Override with `bar:`/`fill:` colors.80- `htable(cols, header, ..rows, aligns: none)` — accent-header, zebra-body81 table. `header` and each row are arrays of content cells.82- `theme` — the color dictionary (`theme.accent`, `theme.muted`, `theme.rule`…).8384Do **not** re-declare page setup, fonts, heading styles, or table colors in the85project file — inherit them from the template so a future style change is a86one-file edit.8788## Section structure8990Use numbered level-1 headings so the table of contents reads as a build order.91Include a section only when the project uses it:92931. **Overview** — what it is, architecture in 1–2 paragraphs, `callout`s for the94 headline facts (e.g. core split, "what you get").952. **Bill of Materials** — `htable` of Qty / Component / Notes, then a short96 "Tools required" paragraph. Flag voltage gotchas with a `warn` callout.973. **System Architecture** — embed the schematic via `#figure(image(...))`;98 explain the bus/topology in prose.994. **Wiring Reference** — subsections of `htable`s derived from `pin_config.h`:100 GPIO map, I²C topology, PWM/expander channel map, sensor pinouts.1015. **Power** — rails, source, and a `danger` callout for the common-ground rule.1026. **Assembly Steps** — an ordered `+` list, power-first, ending with a103 pre-power-up continuity check.1047. **Build & Flash** — real `just <module>::*` recipes in a code block, flash105 offsets table (from justfile / partitions.csv), download-mode `warn` callout.1068. **First Boot & Provisioning** — WiFi provisioning (Improv/creds), mDNS107 hostname, AI backend, OTA.1089. **Functional Checkout** — an `htable` of tick-box (`☐`) checks vs expected109 results, ordered to match assembly.11010. **Troubleshooting** — `htable` of Symptom / cause & fix, seeded from the111 board's known failure modes and load-bearing sdkconfig settings.112113End with a small muted footer line pointing at the authoritative sources114(`pin_config.h`, any ADR) and the regenerate command.115116## Compiling117118Typst is not part of the container toolchain. If `typst` is missing, install the119CLI from crates.io (GitHub release binaries are blocked by the egress proxy):120121```bash122CARGO_HTTP_CAINFO=/root/.ccr/ca-bundle.crt cargo install typst-cli --locked123```124125Compile from the guide's directory with the **repo root** as the sandbox root so126the template import and shared schematic image resolve (both live outside the127project dir). Use the **canonical flags** — the `build-guide-check.yml` CI guard128recompiles every guide and fails if the committed PDF differs byte-for-byte, so129the PDF must be produced deterministically:130131```bash132cd packages/<domain>/<project>/docs133typst compile --creation-timestamp 0 --ignore-system-fonts --root ../../../.. build-guide.typ134```135136- `--creation-timestamp 0` pins the embedded PDF timestamp; without it the file137 carries wall-clock time and never reproduces.138- `--ignore-system-fonts` embeds only Typst's bundled fonts, so glyph fallbacks139 are identical on every machine (otherwise Linux FreeSans vs macOS SF diverge).140- Match the Typst version the guard pins (see `TYPST_VERSION` in141 `.github/workflows/build-guide-check.yml`); a different compiler release142 produces different bytes. Install it with143 `cargo install typst-cli --version <that-version> --locked`.144145Verify by rendering a page or two to PNG (`--pages 1,3`) and eyeballing the146layout before committing.147148Commit **both** `build-guide.typ` and `build-guide.pdf` — the PDF is the149deliverable and lets people use the guide without installing Typst.150151## Wiring up the README152153Add a short "Printable build guide" section to the project `README.md` linking154`docs/build-guide.typ` and `docs/build-guide.pdf`, plus the regenerate command.155156## Style rules157158- **Authoritative pins** — every pin, address, channel, and offset comes from159 source (`pin_config.h`, `partitions.csv`, `justfile`). If source and prose160 disagree, trust source and flag it.161- **Fill, don't pad** — omit sections the project doesn't use. A tight 6-page162 guide beats a padded 12-page one.163- **One style, one file** — never copy the template's styling into the project164 guide; import it. Improvements go in `tools/typst/build-guide.typ`.165- **Callouts for hazards** — voltage mismatches, common-ground, PSRAM mode,166 download-mode go in `warn`/`danger` callouts, not buried in prose.167- **Keep meta honest** — read `sdkconfig.defaults` and the justfile for the meta168 box; don't invent toolchain versions.169- **Never print the firmware version** — the template's `version:` parameter170 exists but must stay unset, and nothing generated into `docs/auto/` may read171 `version.txt`. release-please bumps `version.txt` without touching any of the172 drift guard's trigger paths, so the committed PDF silently goes stale, and173 regenerating it is a `docs:` commit that mints the next release — a loop that174 never converges. Cite `version.txt` as the source of truth by name if the175 guide needs to; never interpolate its contents. See issue #439.