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

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.

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

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.