Closed general

First-class STABLE IMAGE URL for a page's current hero (hero.png path is a trap)

John Lauer · 2mo ago ·closed by Colby Knox

The JSON side of hero resolution is first-class and works great: adom-wiki page hero <ref> / GET /api/v1/pages/<ref>/hero returns {url, sha256, bytes, updated_at} naming the page's CURRENT hero file (no-cache, CORS *).

But there is no stable IMAGE URL, and the obvious guess is a trap: https://wiki.adom.inc/<owner>/<slug>/hero.png happily returns 200 serving whatever repo file happens to be named hero.png, which is usually a STALE, superseded hero. Pages actually keep their current hero wherever they like (docs/hero.png, screenshots/hero.png, hero-v9.png, adom-chipsmith-hero-v4.png, ...).

Real-world damage (Hydrogen hero deck audit, 2026-08-11): the deck embedded <page>/hero.png URLs for its 7 live apps. Result: 6 of 7 served outdated heroes, e.g. adom/pup-bridge returned a 268KB stale copy while the page's real hero is hero-v9.png (392KB, set 2026-08-09). Any plain <img> embedder (readmes, dashboards, external sites) will fall into the same hole, and a 200 response makes it invisible.

Request: a first-class, stable image endpoint that always serves (or 302s to) the page's current hero bytes, e.g.:

  • GET /api/v1/pages/<ref>/hero.png (image twin of the existing JSON endpoint), or
  • make /<owner>/<slug>/hero.png an alias that resolves through page.json instead of the repo tree.

With sensible cache semantics (ETag = the hero's sha256, or no-store like today's hero files). That gives <img src> embedding without a JSON hop and kills the silent-staleness failure mode.

2 Replies

John Lauer · 2mo ago

Follow-up proposal that goes further than the alias: make hero.png consistency REAL by changing how heroes are stored, and make regeneration (not storage) the history mechanism.

1. Clobber old heroes; the latest is always hero.png. The wiki and Hero Studio should stop accumulating hero-v9.png / *-hero-v4.png files. On every hero set: write the new image to hero.png (one canonical name, every repo the same) and delete the superseded image (or at most shunt it to an old- name briefly). Old hero images are pure repo bloat: they are regenerable artifacts, not source, and nobody ever browses them. Multi-hundred-KB PNGs pile up in page repos forever today.

2. The thing worth storing is the RECIPE, not the pixels: a hero-creation skill. When a hero is set, the wiki/Hero Studio should ensure the repo carries a skill documenting how that hero was made, at a standard path: skills/hero-creation/skill.md. Two flows:

  • Hero Studio exports what it knows (layout, theme, accent, source screenshots) into that skill automatically, and
  • better: it asks the CALLING ai-thread to write the skill for how it created its own hero (most threads figure out gold like "screenshot my own app in a pup window, resize to the vitrine aspect ratio so no cropping occurs" and then never write it down, so the next thread re-derives it from scratch).

On the next update, Hero Studio tells the calling thread which skill was last used (or that one exists at the standard path), and coaches best practices into it. The skill is the durable asset; the image is a build artifact.

3. Net effect.

  • Every wiki repo has exactly one hero.png (plain <img> embedding works and is always current, no alias endpoint even needed).
  • Repos stop bloating with dead images because history is "re-run the skill", not "keep the old pixels".
  • Hero quality compounds: each update starts from the documented recipe instead of from zero.
Colby Knox · 2mo ago

Shipped and live on prod. A first-class stable hero IMAGE url: GET /api/pages///hero.png (the /api/v1/... form works via the router rewrite) always serves the page CURRENT hero, resolved through page.json (billboard composes its SVG; image/video serve the repo file at hero_path), never a literal hero.png. The pretty path ///hero.png now resolves the current hero for public pages too, so existing embedders stop silently serving a stale hero; it falls through to the normal repo-file handler for private pages or when there is no current hero. Public pages only (edge-cacheable image URL, like hero-thumb.png), ETag = git blob sha (billboard: tip commit), no-cache bare and immutable with ?v=. Verified on staging with a repro: a page carrying a stale hero.png file AND hero_path=hero-v2.png serves hero-v2.png at both paths, and the image bytes sha256 match the JSON /hero endpoint.

Log in to reply.