After the P03/P04 entry landed, the site’s two viewers and two file-rendering components needed a real annotation story. They got one over the next two hours, mostly by borrowing patterns from the pine64-freebsd notes site and adapting them to a chip context.
What happened
Started with line annotations. Source.astro and Diff.astro both
grew an annotations: { match, text }[] prop. A Shiki transformer
walks the highlighted code’s child line spans and splices an <aside>
sibling immediately after each matched line. First pass put the notes
inline (italic, warning-tinted, └── glyph prefix). Second pass moved
them to a side panel because copying code from the page picked up the
prose, which was bad. Third pass: the side notes are absolutely
positioned per-target-line, with a JS pass measuring offsetTop and
walking the list pushing later notes down so they don’t overlap.
Container-query fallback to a stacked layout below 760px.
Then chip-coordinate annotations on the LayoutViewer (2D) and
ChipViewer (3D). Same prop shape: { x_um, y_um, w_um, h_um, label, text, layers? }, in fab µm, DEF convention, origin at die
bottom-left. The 2D viewer reprojects markers every animation frame
through the live viewBox; the 3D viewer raycasts a wireframe
LineSegments box (with an invisible solid pick-mesh twin, because thin
line geometry is unreliable as a click target). Layer toggling is
folded in: clicking an annotation can hide every layer except the
ones that matter for that callout.
The two viewers cross-talk via a vp-anno custom event. Click an
annotation card in the central panel and both viewers focus on it
simultaneously. The annotation panel itself eventually moved out of
each viewer and into the ViewerPair wrapper’s grid column 2, with
per-viewer panels collapsing when the central one is rendered, so
there’s never a duplicate list.
UX iterations along the way: click-only (no hover layer toggling, too twitchy), only the active annotation’s box renders (the wireframes were too noisy), the ChipViewer canvas had to fight to fill its column rather than hold a 16:10 aspect with empty space below.
Closing the session: a <Term> component plus /glossary page. About
30 acronyms (UART, SPI signals, CDC, sky130 layers, EDA tools) defined
once in src/data/glossary.ts. <Term> wraps a word in <abbr title>
with a dotted underline and links to /glossary#slug. Applied across
the first acronym mentions on the P03 and P04 pages.
Receipts
6ed4582— viewers side-by-side; double-flip y bug insvg_to_shapes.pyfixed (the chip was rendering in a thin top strip the whole time).3251258— line annotations forSourceandDiff.82e4c01— annotations to side panel, P03 console demo.41f0c72— demo testbenches for P01/P02/P04.10d5c02— chip-coord annotations on both viewers, cross-viewer sync.5ab7af3,b8cfff8,591dc83,6ae55a4,1f81148,ea153a2— the annotation panel’s many small UX fixes.2d75409— P02 annotations call out the counter, LFSR, PWM regions from the placed netlist.b69a8aa—<Term>+/glossary.
Files of note:
/site/src/components/Source.astro, /site/src/components/Diff.astro,
/site/src/components/LayoutViewer.astro,
/site/src/components/ChipViewer.astro,
/site/src/components/ViewerPair.astro,
/site/src/components/Term.astro,
/site/src/data/glossary.ts,
/site/src/pages/glossary.astro.