agr.media
Unified image CDN with on-the-fly transforms via Sharp and Cloudflare edge caching.
agr.media
A stateless image CDN that optionally transforms images with Sharp and serves them through Cloudflare's edge cache. It replaces the per-client DNS image hosting pattern with a single unified endpoint.
- Domain:
agr.media
URL Pattern
https://agr.media/{clientDomain}/{folder}/{path}
https://agr.media/{clientDomain}/{folder}/{transforms}/{path}| Segment | Description |
|---|---|
clientDomain | The client's domain (e.g., example.com) |
folder | images or media (only allowed folders) |
transforms | Optional comma-separated key_value pairs |
path | File path relative to the folder (may include subdirectories) |
Transforms
| Key | Values | Example |
|---|---|---|
w | 1–4096 | w_800 |
h | 1–4096 | h_600 |
q | 1–100 | q_80 |
f | auto, webp, avif, jpeg, png | f_webp |
fit | cover, contain, fill, inside, outside | fit_contain |
Transforms are combinable: w_400,f_webp,q_80
Examples
# Original image (pass-through, no transforms)
https://agr.media/example.com/images/logo/hero.jpg
# Resize to 400px wide
https://agr.media/example.com/images/w_400/logo/hero.jpg
# Resize + convert to WebP
https://agr.media/example.com/images/w_400,f_webp/logo/hero.jpg
# Resize + quality adjustment
https://agr.media/example.com/images/w_800,q_60/logo/hero.jpgCaching
| Layer | Header | TTL |
|---|---|---|
| Browser | Cache-Control: public, max-age=86400 | 24 hours |
| Cloudflare edge | Cloudflare-CDN-Cache-Control: max-age=3600, stale-while-revalidate=86400, stale-if-error=604800 | 1 hour TTL, SWR/SIE |
- ETag is based on file size + mtime — revalidation works when source files change
- Vary: Accept is set on transformed images for content negotiation
- No
immutable— images may be replaced at the same path - No origin disk cache — Cloudflare edge is the only cache layer
Design Decisions
- Stateless containers — any container can handle any request, no shared state
- In-flight deduplication — concurrent requests for the same transform coalesce into one Sharp operation
- SVG loading blocked —
VipsForeignLoadSvgis disabled for security - Max input size — 50 MB per image