Image optimization
Every project answers /_slew/image — a resize-and-recompress endpoint for the images already on your site. Ask for a width, get a WebP sized to it, served and cached by the CDN edge:
<img
src="/_slew/image?url=/photos/hero.jpg&w=1080"
srcset="/_slew/image?url=/photos/hero.jpg&w=640 640w,
/_slew/image?url=/photos/hero.jpg&w=1080 1080w,
/_slew/image?url=/photos/hero.jpg&w=1920 1920w"
sizes="100vw" alt="…">
There is nothing to enable and nothing to configure. A 1 MB photo typically comes back a tenth the size; the transformation happens off your instance, so a request for an image never wakes a scaled-to-zero server.
Parameters
| Parameter | Meaning |
|---|---|
url |
Path of the source image on the same site (/photos/hero.jpg). Absolute URLs to other hosts are rejected. |
w |
Target width in pixels. One of 16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840 — the allowlist bounds how many variants one image can produce. Anything else is a 400. |
q |
Optional quality, 1–100, default 75. Snapped to the nearest of 25, 50, 75, 90. |
Images are never upscaled: a 800px-wide source requested at w=1080 comes back 800px wide.
What gets optimized
JPEG and PNG sources are resized and re-encoded as WebP. Everything else — SVG, GIF, WebP, AVIF, or a url that isn't an image at all — answers with a redirect to the original file, so an <img> pointing at the endpoint always renders something. The same fallback applies to sources over 10 MB and to any transformation error: worst case is your original, unoptimized image.
Caching
Variants cache at the CDN edge effectively forever and are evicted by the same purge a deploy triggers — ship a new version of /photos/hero.jpg and its variants regenerate on first request. Browsers cache variants for an hour. The first request for a given url × w × q pays the transformation (around a second for typical photos, a few seconds for very large ones); every request after that is an edge cache hit.
On password- or org-protected sites the access gate applies to image variants like any other URL, and each unlocked visitor's variants are cached separately at the edge — the same cookie-keyed caching the rest of a protected site uses.
Using it from Next.js
next/image normally optimizes in your server process. Point it at the platform instead with a one-line custom loader — Next's default device sizes are exactly the width allowlist:
// next.config.js
module.exports = {
output: 'standalone',
images: { loader: 'custom', loaderFile: './slew-image-loader.js' },
}
// slew-image-loader.js
export default function slewLoader({ src, width, quality }) {
return `/_slew/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality ?? 75}`
}
Your <Image> components are unchanged; the transformation moves from your instance to the platform. Remote images (an https:// src) still go through Next's own optimizer — the endpoint only serves same-site sources.
Limitations, stated plainly
- Output is always WebP. Every browser slew supports renders it; AVIF is on the roadmap.
- Sources must live on the same site. Remote-image allowlists are deliberately not supported yet.
- Sources over 10 MB serve unoptimized.
- Available on projects, not on temporary shares.