Image Pipeline
AstroMerchant lets you paste any HTTPS image URL (from your CDN, S3, ImageKit, Unsplash, etc.).
We generate responsive variants (AVIF/WebP with a JPEG or PNG fallback), add intrinsic width/height to prevent CLS, and cache results.
There are two paths images can take:
- Astro components (product grids, blog cards, etc.) use Astro’s
<Image />
via Netlify Image CDN at/_image
(edge-cached). - React/client components (e.g., search grid) use our SSR endpoint
/api/img
(long-lived cache headers).
Supported input formats
- ✅
jpg/jpeg
,png
,webp
,avif
,svg
,gif
,tiff
,heic/heif
- ⚠️ Animated formats are treated as static (first frame).
- ✅ Only HTTPS sources are accepted.
Output formats
By default components serve:
formats={['avif','webp','jpeg']}
Browsers pick the best option via <picture>
.
Transparency: If a source has alpha and jpeg
is requested, the pipeline automatically serves PNG for that variant to preserve transparency.
Caching
/_image
(Astro + Netlify Image CDN): transformed assets are edge-cached./api/img
(SSR endpoint): responses include
Cache-Control: public, max-age=31536000, immutable
so unique variants by querystring are cacheable.
Domain allow-list (remote images)
Remote hosts must be allowed, otherwise requests are blocked.
Netlify (for /_image
)
netlify.toml
[images]
remote_images = ["ik.imagekit.io/*", "images.unsplash.com/*"]
Local dev .env
NETLIFY_IMAGE_CDN_ALLOWED_REMOTE_DOMAINS=ik.imagekit.io,images.unsplash.com
/api/img
endpoint
Uses the same env var (or IMG_ALLOWED_DOMAINS
) to restrict hosts:
# either of these is supported
NETLIFY_IMAGE_CDN_ALLOWED_REMOTE_DOMAINS=ik.imagekit.io,images.unsplash.com
IMG_ALLOWED_DOMAINS=*.examplecdn.com,assets.myapp.com/*
If the list is empty,
/api/img
allows all HTTPS hosts (dev-friendly).
If set, only matching hosts are allowed (supports exact and*.domain.com
).
Size limits (safety & performance)
- Max requested width: 4096px (
MAX_W = 4096
)
Larger requests are clamped. - Max input pixels: ~16k × 16k (
limitInputPixels = 268435456
)
Prevents pathological source files. - No enlargement: we don’t upscale beyond the source size.
Extremely large/invalid sources may return a 4xx/5xx error.
Recommended source sizes
- Product heroes & blog headers: 1600–2400px wide
- Gallery/detail images: 1200–1600px wide
- Thumbnails/cards: ≤ 800px (we downsize anyway)
Typical usage
Astro components (already wired in the theme):
<Image
src={imageUrl}
alt={title}
widths={[640,768,1024,1280,1600,1920]}
sizes="(min-width:1024px) 50vw, 100vw"
formats={['avif','webp','jpeg']}
/>
React components (use our API route):
const u = encodeURIComponent(src);
const url = `/api/img?u=${u}&w=640&f=webp`;
// Optional 2x srcset for crisp thumbs:
const srcset = `/api/img?u=${u}&w=640&f=jpeg 1x, /api/img?u=${u}&w=1280&f=jpeg 2x`;
Common errors & fixes
- “Host not allowed” → Add the domain to the allow-list (see above) & restart dev.
- “Only https:// images are allowed” → Use HTTPS URLs.
- “Upstream fetch failed” → Source URL is invalid/private/down; verify it opens in a browser.
- Blank/stub images in dev → Ensure
.env
allow-list is set; restartastro dev
; hard refresh.
Changing the max width (advanced)
If you need outputs wider than 4096px, raise MAX_W
in both:
src/image/netlify-universal-service.ts
src/pages/api/img.ts
Larger outputs increase CPU/memory usage and response time. Change with care.
TL;DR for buyers
- Paste HTTPS image URLs from your CDN/storage.
- We auto-generate modern formats and responsive sizes with proper width/height to avoid layout shift.
- There’s a max output width of 4096px; huge source files are limited for safety.
- If a host is blocked, add it to the allow-list (
ik.imagekit.io
,images.unsplash.com
, etc.).