Skip to content

Writing guides

Last updated:

This page is the reference for guide authors. Everything below is enforced by convention and code review, not by the system itself — which is what keeps the format consistent across guides without locking us into a rigid schema.

For a complete worked example that exercises every convention here, see Reference Assembly — a deliberately fake guide kept up to date as the canonical structural template.

Each guide is a folder under src/content/docs/guides/:

src/content/docs/guides/<slug>/
├── index.mdx # the guide content
├── step-1.png # images, co-located with the guide
├── step-2.png
└── ...

Images are referenced relatively (./step-1.png) so Astro’s asset pipeline picks them up and emits optimized WebP variants at build time.

Every guide starts with a small <table class="guide-meta"> block holding the basic facts:

FieldWhat it means
ProductAssembly name.
Hardware revThe hardware revision this guide applies to. Bump when the hardware changes. Do not bump for typo fixes or wording changes — git is the source of truth for instruction history.
AuthorOriginal author.

The page’s lastUpdated date and time come automatically from git history and render under the title — you don’t author it.

A step is one image worth of work that ends in a verifiable state change.

Three properties any step must satisfy:

  1. One photo per step. If you find yourself wanting two photos, it’s two steps.
  2. Verifiable end state. After the step, the assembly is visibly different in a way the builder can confirm. Pure setup actions (“place in fixture”) are not steps unless they leave a visible result.
  3. Independently undoable. Reversing step N returns the assembly to the state at the end of step N−1. If undoing requires touching earlier steps, the boundary is wrong.

Heuristics that fall out:

  • “And” in a step is a smell — likely two steps.
  • A step whose only verb is “tighten” referring to a screw placed earlier should be merged with that earlier step.
  • Long-cure / wait steps are valid (they have a verifiable end state and can’t be merged).
  • Target the junior tech for granularity. Senior techs skim past granular steps; juniors fail at batched ones.

Use H2 headings to group steps into sub-assembly milestones:

## Main board prep
### 1. Mount the main board
...
### 2. Seat the ribbon connector
...
## Sensor head
### 3. Install the sensor module
...
  • Numbering is continuous across groups (1, 2, 3, 4…), not reset per group. Builders refer to “step 7” verbally; group resets break that.
  • No single-step groups. If a group has one step in it, it isn’t a real boundary — fold it into a neighbor.
  • No nesting. H4 sub-steps inside H3 steps inside H2 groups is forbidden.
  • Group titles name the sub-assembly milestone (“Sensor head”), not the step range (“Steps 3–6”).
  • Break a group out into its own guide only when it’s built at a different time, by a different person, or on a different bench setup.

Each step opens with an italic line listing what the step consumes:

### 3. Install the sensor module
_Parts: 1× sensor module, 2× M2×6 SHCS. Tools: 1.5 mm hex key._
![...](./step-3.png)
Instruction text...

Conventions:

  • Include Parts: and Tools: when present, omit when not. Don’t write “Tools: none.”
  • The aggregated BOM is derived from per-step lines, not authored separately. There is no top-of-page BOM section. If you find yourself wanting one, it means the procurement view should be a build-time aggregation — file an issue.
  • Every part in the assembly should appear in some step. Decals, desiccant, foam inserts — they all belong in steps (often a final pack-out step). If a part doesn’t fit any step, the steps are incomplete.

For warnings or info inside a step, use Starlight’s <Aside>:

<Aside type="caution">
Torque to 0.4 N·m. Over-torque cracks the housing.
</Aside>

Types: note, tip, caution, danger. Use sparingly — only when something genuinely matters to a builder on the floor.

To call out specific points on a photo, wrap the image in <AnnotatedImage> and add numbered bubbles:

import step1 from './step-1.png';
<AnnotatedImage src={step1} alt="...">
<Bubble at={[15, 70]} number={1} />
<Bubble at={[50, 85]} number={2} />
</AnnotatedImage>
Lift the rear housing carefully — the flex cable (1) is short, so do not pull beyond 30°. The battery (2) remains seated.

Coordinates are percentages of image dimensions (0–100), naming the center of the bubble. Percentages survive image re-exports at any resolution.

Live example:

Sample annotated image with three differently-colored bubbles
1 2 3

Bubbles default to red. Pass a color prop to change it:

<Bubble at={[50, 50]} number={2} color="blue" />

Available colors: red (default), green, blue. The dev panel has three matching swatches — click one to make it active, then click an existing bubble to repaint or click empty image area to add a new bubble in that color.

Use color sparingly — if every bubble is a different color, none of them stand out. Stick to red unless a bubble means something genuinely different (e.g., red for parts being added, green for the orientation reference point, blue for an alignment guide).

In npm run dev, every <AnnotatedImage> exposes a small panel below it:

  • Click empty image area → drops a new bubble there, auto-numbered.
  • Drag a bubble → reposition. The readout updates live as you drag.
  • Shift+click a bubble → removes it, renumbering remaining bubbles to stay sequential.
  • Click “Save” → rewrites the <Bubble> lines in the MDX file directly. The dev server then hot-reloads.

If “Save” reports failure, the most likely cause is a conditional or self-closing <AnnotatedImage> in the source. Open it to a normal <AnnotatedImage>...</AnnotatedImage> form and retry.

The dev panel and endpoint are gated behind import.meta.env.DEV — they don’t exist in production builds.

  • Conditional branches per hardware rev — branch the whole guide per rev instead of putting “if rev B, do this” into a step. Conditional steps break the independently-undoable property and confuse builders.
  • Recovery hints — put inside an existing step as an <Aside>, not as their own step.
  • Workspace setup — put in a “Before you start” section above the first H2 group, not as a numbered step.

After the last step, add a ## Verification section with observable checks the builder runs before shipping the assembly:

## Verification
- [ ] All four perimeter screws sit flush.
- [ ] No gap between housings exceeds 0.2 mm at any edge.
- [ ] LED illuminates when power is applied.

These are inspection-only and shouldn’t appear as steps — they don’t change state, they confirm state.