Skip to content

v2.3.0 — Image variants on AssetRef

Choose a tag to compare

@MajorTal MajorTal released this 19 May 16:02
· 1213 commits to main since this release
2836633

Surfaces the v1.49 gateway image-variant pipeline in @run402/sdk, run402 (CLI), and run402-mcp. Additive, non-breaking — old clients silently ignore the new fields. Lockstep release across the three packages.

What's new for developers

Image uploads now return rich metadata. Upload a JPEG/PNG/WebP/HEIC/HEIF via r.assets.put(...) or r.project(id).apply({ assets: { put: [...] } }) and the returned AssetRef carries:

  • width_px, height_px — display-oriented dimensions (post-EXIF rotate)
  • blurhash — LQIP placeholder, decode client-side
  • variants.thumb (320w WebP), variants.medium (800w WebP), variants.large (1920w WebP)
  • display_url — browser-renderable URL; equals cdn_url for jpeg/png/webp, points to a generated JPEG transcode for HEIC/HEIF
  • variants.display_jpeg — full-resolution JPEG transcode (HEIC/HEIF sources only)

Both write paths produce structurally identical AssetRef shapes.

New typed convenience getters — foolproof for non-images.

  • ref.thumbUrl — single field for grid thumbnails. undefined for non-image AssetRefs, so TypeScript narrows and a picker that does `` is a compile error rather than a broken thumbnail at runtime.
  • ref.displayUrl — single field for browser-renderable URL. undefined for non-images. HEIC sources transparently get the JPEG transcode.

New ref.imgTagWithSrcSet(opts) helper — emits a <picture> with WebP-only sources at 320w / 800w / 1920w and display_url as the <img> fallback. Throws at call time on missing opts.sizes (browsers over-fetch the largest candidate without it) AND on missing variants (use imgTag() instead). No silent fallback.

ref.imgTag(alt?) now HEIC-aware. Default <img src> is display_url ?? cdn_url, and width/height attributes are opportunistically emitted when known (eliminates CLS for image grids). Never throws on absence.

MCP assets_put tool output surfaces Dimensions, Blurhash, Display URL (HEIC only), and a Variants: line listing kind + size + format. CLI is JSON-only by design — new fields flow through JSON.stringify automatically.

Out of scope (deliberate)

  • @run402/functions types — that package lives in the private gateway monorepo and ships on its own cadence via /publish-functions. The runtime returns the new fields regardless.
  • AVIF generation — deferred; <picture> type-precedence footgun means AVIF must land at all three sizes simultaneously or via a dedicated imgTagHero() helper.
  • On-demand ?w=N&fmt=webp resize and project-configurable variant sizes — separate future changes.

Links