Context
Kychon portals are image-heavy: hero backgrounds, event covers, member avatars, image accordions, slideshows, media library thumbnails. The Run402 image pipeline already handles AVIF/WebP derivatives for some formats (see existing internal pipeline noted in Kychon's docs/wild-apricot-port-friction-2026-04-30.md), but apps still have to:
- Display the original full-size image as a thumbnail in admin UIs (no thumbnail derivative is returned).
- Hand-write Astro
<Picture> components and pick which derivative to load at which breakpoint.
- Live without blurhash / LQIP placeholders, so cold image loads cause CLS or empty space.
Kychon's upcoming media library (admin-content-management change) needs to render a 4-column grid of image thumbnails. With current behavior, scrolling 8 visible items pulls 8 × full-resolution images — easily 10–20 MB per picker open for a club with high-res photos.
Current friction
assets.put() returns a single cdnUrl for the original upload only.
- There is no thumbnail derivative URL returned, so admin UIs must load the original.
- No blurhash / dominant color / LQIP placeholder is generated, so apps either ship custom
<canvas> blurhash decode or accept layout shift on image load.
- HEIF decode failure (also tracked in Kychon's friction doc, F4) is a related gap in the same pipeline.
Desired outcome
On assets.put() of an image, automatically generate and return derivative URLs:
const ref = await assets.put('images/hero.jpg', bytes, { contentType: 'image/jpeg' });
// ref = {
// path: 'images/hero.jpg',
// cdnUrl: '...',
// variants: {
// thumb: { url: '...', width: 200, height: 200, format: 'webp' },
// medium: { url: '...', width: 800, format: 'webp' },
// large: { url: '...', width: 1920, format: 'webp' },
// avif: { url: '...', format: 'avif' }
// },
// blurhash: 'LEHV6nWB2yk8pyo0adR*.7kCMdnj' // ~30 bytes
// }
Variant sizes could be configurable via a project-level config, with sensible defaults (200 / 800 / 1920 covers most web use cases).
Ideally also:
- Add HEIF/HEIC decode support (closes the existing F4 friction).
- Serve variants with long cache-control headers (they're content-addressed).
- Support on-demand variant generation via URL params (
?w=400&fmt=webp) for use cases not covered by the default variant set.
Why it matters
- Media picker UIs become 50–100× lighter (4 KB thumbnails vs 2 MB originals).
- Blurhash placeholders eliminate CLS on image-heavy pages without app-side LQIP machinery.
- Performance is the most-cited Wild Apricot complaint Kychon tries to fix; this is foundational.
- Any Run402 app using images benefits — not just Kychon.
Workaround until shipped
Kychon's media library will load original images as thumbnails, accepting the bandwidth cost. We will not implement custom blurhash generation in the admin-content-management change; cold image loads will continue to cause minor CLS until this lands.
Related Kychon change
/Users/talweiss/Developer/kychon/openspec/changes/admin-content-management/ — specifically the MediaPicker grid in specs/media-library/spec.md.
Related friction items
- Kychon friction doc F4: HEIF decode support gap (
docs/wild-apricot-port-friction-2026-04-30.md)
Context
Kychon portals are image-heavy: hero backgrounds, event covers, member avatars, image accordions, slideshows, media library thumbnails. The Run402 image pipeline already handles AVIF/WebP derivatives for some formats (see existing internal pipeline noted in Kychon's
docs/wild-apricot-port-friction-2026-04-30.md), but apps still have to:<Picture>components and pick which derivative to load at which breakpoint.Kychon's upcoming media library (admin-content-management change) needs to render a 4-column grid of image thumbnails. With current behavior, scrolling 8 visible items pulls 8 × full-resolution images — easily 10–20 MB per picker open for a club with high-res photos.
Current friction
assets.put()returns a singlecdnUrlfor the original upload only.<canvas>blurhash decode or accept layout shift on image load.Desired outcome
On
assets.put()of an image, automatically generate and return derivative URLs:Variant sizes could be configurable via a project-level config, with sensible defaults (200 / 800 / 1920 covers most web use cases).
Ideally also:
?w=400&fmt=webp) for use cases not covered by the default variant set.Why it matters
Workaround until shipped
Kychon's media library will load original images as thumbnails, accepting the bandwidth cost. We will not implement custom blurhash generation in the admin-content-management change; cold image loads will continue to cause minor CLS until this lands.
Related Kychon change
/Users/talweiss/Developer/kychon/openspec/changes/admin-content-management/— specifically the MediaPicker grid inspecs/media-library/spec.md.Related friction items
docs/wild-apricot-port-friction-2026-04-30.md)