---
name: kicad-bridge-hero
user-invocable: false
description: DEVELOPER-only skill (user-invocable:false — maintainers, never everyday users). The complete recipe for making/refreshing the kicad-bridge page hero in the Adom bridge-family style (matching Pup and Fusion), getting it through the Hero Studio human gate, and applying it to the page + pkg. Encodes every measured layout number, the brand font doctrine, the real-window vitrine capture workflow, and the gate/publish traps we hit shipping the first one. Trigger words — kicad hero, hero image, new hero, refresh hero, hero studio, HERO_STUDIO_REQUIRED, HERO_REQUIRED, bridge family hero, page billboard.
---

# kicad-bridge-hero

How the kicad-bridge hero gets made. First shipped 2026-08-09 after ~14 iterations;
this skill exists so the next one takes two. Full papercut list we filed upstream:
**adom/hero-studio issue #566** — read it before assuming the studio guides you.

## The one-command core

```bash
python3 skills/kicad-bridge-hero/compose_hero.py <vitrine-capture.png> /tmp/hero-vNN.png
```

`compose_hero.py` (in this directory) clones Pup's measured geometry, renders the
title/subtitle, drops in your capture, and **asserts the ink alignment** before saving.
It needs `reference-pup-hero.png` — Pup's true published asset, the source of the logo
crop, pill crop, background gradient corners, and every layout number. It lives in the
kicad-bridge **page repo** next to this skill (not in the pkg tarball — no-images rule);
if missing locally: `adom-wiki repo download pup-bridge --extract /tmp/pup-repo` and
copy `hero-v9.png` in (NOT `repo show` — it mangles binaries to UTF-8).

## Brand doctrine (things John corrected us on — do not rediscover)

- **Title font is Familjen Grotesk BOLD (700)**, not Satoshi. The rule lives in
  hero-studio's own billboard CSS (`.h-title`), nowhere else. Satoshi is for the
  subtitle (inherited from body) and UI chrome. Fonts live in
  `skills/kicad-tour/hero/fonts/`.
- **Title is just "KiCad"** — the one word users type to their AI. The wiki page
  title ("KiCad - the KiCad Bridge") carries the rest dynamically.
- **One pill, baked, at Pup's exact spot** (crop `(1796,36,1964,108)` from the
  reference, pasted verbatim). No second pill, no baked wiki URL: the homepage
  overlay adds its own dynamic pill/slug at render time.
- **Left ink edges must be logo 79 / title 83 / subtitle 83** — title and subtitle share
  one left line. NOTE: Pup's own published hero has its title 14px right of its subtitle;
  John flagged that as misalignment when we copied it, so do NOT clone Pup's stagger.
  Fonts lie about bearings (Familjen reported 0 for "K", drew 16px) — always
  measure rendered pixels and correct; the script does this automatically.
- **Vitrine = Pup's floating-window rect**: (920,150), 1030x1025, radius 24, soft
  shadow. It does NOT bleed any edge (we assumed bleed for days; measurement says no).
- NO em-dashes in any hero/subtitle copy.

## Vitrine capture (real window, never a mockup)

1. Board: `tour-pack-rp2040/template/rp2040-breakout.kicad_pcb` (the annotated
   J1 USB-C / U1 QFN / Y1 crystal board). Ship it over if needed:
   `send_files {"filePaths":[...], "dest":"C:/Users/<u>/Documents/adom-kicad-rp2040"}`
   (the arg is `dest`, not destDir — wrong arg silently lands in Downloads).
2. `kicad_open_board {"filePath":...}` (absolute Windows path; no %VAR% expansion),
   then `kicad_open_3d_viewer`.
3. **Resize the 3D viewer to the slot before capturing** so the capture drops in
   1:1 with zero scaling: `desktop_set_window_bounds {"hwnd":N,"x":200,"y":20,"w":1030,"h":1025}`
   (args are w/h, not width/height).
4. Dark mode: Windows OS dark mode gives KiCad 10 dark titlebar/menus/panels. The
   3D viewport background is theme-bound (`_builtin_default` isn't editable), so it
   stays lavender — that's fine; Pup's vitrine also pairs a dark card with a light
   window interior.
5. A human-posed camera angle beats anything scripted. Ask John to frame it, then
   `desktop_screenshot_window {"hwnd":N}` — the PNG lands in the container at
   `screenshots/adom-bridge/window/`. Zoom-to-fit is a toolbar click
   (`kicad_click {"hwnd":N,"x":375,"y":100,"relative":false}`); there is no Home-key fit.

## Hero Studio gate (mandatory — registry enforces provenance)

Only the studio's export passes `HERO_STUDIO_REQUIRED`; a human must click Generate.

```bash
node <hero-studio>/server.js --port 88XX &     # OWN port; check `ps` first — port
                                               # collisions once stomped pup's gate
curl -X POST :88XX/state -d '{"mode":"app","page":"adom/kicad-bridge", ...,
  "overlay":{"pill":false,"scores":false,"author":false,"slug":false}}'
hero-studio vitrine --file /tmp/hero-vNN.png --full --port 88XX
```

Traps (all in issue #566):
- **Turn the overlay sim OFF via /state** (above). Its flags default ON, persist
  server-side across reloads, and draw a fake pill + slug URL over your hero —
  three review rounds were lost to "why 2 pills / why a wiki url".
- The reviewer views the gate through **pup**: open the container-proxy URL in a
  session YOU own, `foreground:true` needs a `foregroundReason` quoting the user.
  Signal updates with `pup_alert_window` (taskbar flash), never re-foreground.
- "broken_images_6" on import = empty placeholder slots, not your hero. Verify with
  one screenshot, don't chase it.
- Page renamed recently? The studio caches page data at boot: run its
  `refresh-data.sh`, restart your instance, re-POST state + re-import the vitrine
  (restart wipes in-memory state AND the reviewer's ticked checkboxes — warn them).

## Apply after Generate

```bash
cp <hero-studio>/generated/hero-kicad-bridge-<ts>.png kicad-bridge-hero-vN.png
adom-wiki repo push adom/kicad-bridge --files kicad-bridge-hero-vN.png -m "hero vN: ..."
adom-wiki page hero adom/kicad-bridge --image kicad-bridge-hero-vN.png
```

The generated PNG carries a `tEXt` provenance comment (`generator: hero-studio`) —
that's what the registry checks. Keep the exact file; recompressing strips it.

Then refresh the live page in the reviewer's pup window (cache-bust query param)
and verify the render with a screenshot — never just say "applied".

## Pkg gotcha that looked like a hero problem

`pkg publish` failing `HERO_STUDIO_REQUIRED` with `"reason":"no_hero"` +
`"new_page":true` means your staging `package.json` still has a **stale slug**
(ours said `adom-desktop-kicad-bridge` post-rename, so the registry saw a hero-less
new page). Fix the slug; the pkg needs no `hero` field at all — the check reads the
page. Also: stage from a clean dir; a stale `page.json` overlaid from an old tarball
draws a `PAGE_JSON_IGNORED` warning and can resurrect deleted files.
