Public Access
29ff175e8967c5ee57dce0608127b351baf7bc4b
The endpoint answers 200 application/json with {"Image":"data:image/jpeg;base64,…"} —
a JSON envelope, NOT image bytes. An <img src="…?id=N"> pointed at it never settles:
measured on the live page, complete=false · naturalWidth=0 for 20 s, so the fallback
never fired and the card showed an empty slot. The card now FETCHES the route, reads
`Image` and puts the data URI on an <img> only when it passes the isImageSrc allowlist.
- static/expert-image.js: `load(id)` replaces `url(id, rec)`. It fetches the route,
reads `Image`, accepts the array shape n8n sometimes returns, and resolves to a usable
image source or `null` on ANY failure. EVERY request is bounded by `timeoutMs` (8000):
an AbortController is aborted by a setTimeout, the abort rejects the fetch and lands in
the same catch that returns null — so a hang becomes the monogram, not an empty box.
The timer is cleared on every completion. The decoded URI is cached by id (failures
too), so a re-render or a shared id never re-fetches. Every non-success path — timeout,
abort, non-2xx, {}, a blank/missing Image, a value that fails isImageSrc — ends in the
monogram: never an empty box, never a broken-image icon, never alt text in the layout.
- Directory card (odoo-community-developers/index.html): the monogram reserves the 72x72
box and stands until a real photo has DECODED; the photo is requested lazily, only when
a card nears the viewport (IntersectionObserver, rootMargin 200px), so a 14-card page
does not fire 1.4 MB on load. The monogram and the photo are the same 72x72 box, so the
swap moves nothing (measured: head box 274.81x72 and ask-row tops byte-identical across
a loaded photo and a monogram).
- /freelancer-edit/: the photo preview makes the same fetch, so the form no longer points
an <img> at the JSON route either.
Proved in a real browser against the repo served with the two webhook URLs stubbed:
jpeg data URI -> photo (src prefix data:image/jpeg;base64,/, naturalWidth 800); {} / 404 /
500 / a bad value -> monogram, 0 broken-image icons, 0 cards with neither; a stub that
never answers -> monogram after 8000 ms with the request ABORTED (client abort event at
8000.x ms, all 6 sockets disconnected server-side). No record created, no probe write.
Languages
HTML
91.6%
JavaScript
6.3%
CSS
2.1%