Images that editors upload through TinaCMS are hot-linked from S3 at their original size. On the sites we measured this week, that means multi-megabyte heroes and card images (up to 1.4 MB each, ~7 MB pages), img tags with no width or height (layout shift), and no fetchpriority on the largest image. It's the main reason image-heavy pages score 15-second LCP on mobile even after the caching improvements (#744, #745).
Proposal: render content images through Astro's image pipeline (astro:assets). Our Netlify adapter already backs it with Netlify's Image CDN by default, so the CDN resizes, converts formats, and caches — editors keep uploading originals and nothing is re-uploaded or migrated. inferSize fills in width/height, which Tina doesn't store. Work: add the S3 media bucket to image.remotePatterns, convert the image call sites (page-builder banner and columns, post cards, branding logos), pass computed image props into the React components that need them, and set fetchpriority on heroes.
Two boundaries:
- IIIF images are excluded — the IIIF Image API already serves exact sizes, so those call sites just need an audit that cards and thumbnails request appropriately small derivatives. Don't put the Image CDN in front of the image server.
- Static builds are unaffected: the static-build image pipeline replaces delivery wholesale (durable IIIF URLs), so this applies to server-rendered sites only.
One related design note: the home hero — usually the LCP image — is injected by a server island, so the browser can't discover it from the initial HTML however well it's sized. Worth deciding in this PR whether the Tina-backed content islands (home, pages) should render into the page like the header and footer now do (#745).
Images that editors upload through TinaCMS are hot-linked from S3 at their original size. On the sites we measured this week, that means multi-megabyte heroes and card images (up to 1.4 MB each, ~7 MB pages),
imgtags with no width or height (layout shift), and nofetchpriorityon the largest image. It's the main reason image-heavy pages score 15-second LCP on mobile even after the caching improvements (#744, #745).Proposal: render content images through Astro's image pipeline (
astro:assets). Our Netlify adapter already backs it with Netlify's Image CDN by default, so the CDN resizes, converts formats, and caches — editors keep uploading originals and nothing is re-uploaded or migrated.inferSizefills in width/height, which Tina doesn't store. Work: add the S3 media bucket toimage.remotePatterns, convert the image call sites (page-builder banner and columns, post cards, branding logos), pass computed image props into the React components that need them, and setfetchpriorityon heroes.Two boundaries:
One related design note: the home hero — usually the LCP image — is injected by a server island, so the browser can't discover it from the initial HTML however well it's sized. Worth deciding in this PR whether the Tina-backed content islands (home, pages) should render into the page like the header and footer now do (#745).