Rendering a content image correctly in a JavaScript module today requires knowledge that exists nowhere in the platform — srcset/sizes semantics, resource-vs-CSS pixels, per-provider resize channels, cache dependencies, alt rules — so every module re-derives it (luxe: ~250 lines) and the platform's own tutorial and hydrogen sample teach <img src={buildNodeUrl(cover)} alt="" />: full-resolution original, empty alt, no candidates.
Target: a junior renders a responsive, accessible, cacheable image by declaring intent, and gets it wrong only if they ignore a compile error.
<Image node={imageNode} alt="Bay view from the terrace" layout="constrained" width={400} />
That single line must produce: a per-provider resized src, a srcSet of candidates clamped to the original, a derived sizes, intrinsic width/height (no CLS), loading="lazy" only when those are known, and a registered cache dependency.
Architecture (three tiers, the middle one is what Islands consume):
| Tier |
API |
Owns |
| URL |
buildImageUrl(node, { width, height }) |
provider routing, clamping, no-op detection |
| Props |
getImageProps(node, { alt, layout, width }) |
candidates, sizes derivation, intrinsic dims, cache dependency |
| Component |
<Image node alt layout width priority /> |
the <img>, loading policy, fallback |
Full API sketch in the first comment.
Sub-issues: #735 URL+props tier · #743 component · #744 layout intent · #739 typings (getProvider) · #736 args JSDoc + getThumbnailUrl · #738 Island ImageProps contract · #737 guide + fix the teaching materials · #745 unit-test runner · Jahia/luxe-jahia-demo#456 adopt and delete the userland copy.
Grounding: an image-pipeline audit of Jahia/luxe-jahia-demo (#452, #451) plus a platform-gap analysis of this repo (urlBuilder, Island/hydrate, typings generator, docs, samples), and an API comparison against Astro's astro:assets (DX-COMPARISON-ASTRO.md §5, recommendation 10).
Rendering a content image correctly in a JavaScript module today requires knowledge that exists nowhere in the platform — srcset/sizes semantics, resource-vs-CSS pixels, per-provider resize channels, cache dependencies, alt rules — so every module re-derives it (luxe: ~250 lines) and the platform's own tutorial and hydrogen sample teach
<img src={buildNodeUrl(cover)} alt="" />: full-resolution original, empty alt, no candidates.Target: a junior renders a responsive, accessible, cacheable image by declaring intent, and gets it wrong only if they ignore a compile error.
That single line must produce: a per-provider resized
src, asrcSetof candidates clamped to the original, a derivedsizes, intrinsicwidth/height(no CLS),loading="lazy"only when those are known, and a registered cache dependency.Architecture (three tiers, the middle one is what Islands consume):
buildImageUrl(node, { width, height })getImageProps(node, { alt, layout, width })sizesderivation, intrinsic dims, cache dependency<Image node alt layout width priority /><img>, loading policy, fallbackFull API sketch in the first comment.
Sub-issues: #735 URL+props tier · #743 component · #744 layout intent · #739 typings (
getProvider) · #736argsJSDoc +getThumbnailUrl· #738 IslandImagePropscontract · #737 guide + fix the teaching materials · #745 unit-test runner · Jahia/luxe-jahia-demo#456 adopt and delete the userland copy.Grounding: an image-pipeline audit of Jahia/luxe-jahia-demo (#452, #451) plus a platform-gap analysis of this repo (urlBuilder, Island/hydrate, typings generator, docs, samples), and an API comparison against Astro's
astro:assets(DX-COMPARISON-ASTRO.md§5, recommendation 10).