Homelab · image service

squish

Image transform + render service. Cloudinary-style URL transforms at /cnar; satori-driven template composites at /template.

Static · ~20–70 ms p50 · libvips Animated · ~210 ms p50 · ffmpeg + cwebp /healthz format showdown smart crop quality ladder template path email pixel

Format showdown — /cnar/f_…

Same source image, three output formats at quality 50. Cards have fixed width; smaller outputs sit centered inside their frame.

JPEG at quality 50
JPEG · q50 loading… f_jpg,q_50,w_300,h_250,c_crop,g_faces:auto
AVIF at quality 50
AVIF · q50 loading… f_avif,q_50,w_300,h_250,c_crop,g_faces:auto
Auto-negotiated format at quality 50
auto · q50 loading… f_auto · negotiated via Accept header

Smart crop — g_faces:auto vs. fixed gravity

Squish runs a Pico face cascade on the decoded image and crops to keep the subject in frame. Same input, three crop strategies.

Face-aware square crop
faces:auto · 1:1 loading… g_faces:auto — keeps subject framed
North-gravity square crop
gravity:north · 1:1 loading… g_north — fixed crop, no face detection
South-gravity square crop
gravity:south · 1:1 loading… g_south — fixed crop, no face detection

Quality ladder — q_25 · q_60 · q_90

Same crop, three quality settings. Useful for eyeballing where AVIF compression starts to break down.

AVIF/auto quality 25
auto · q25 loading… aggressive — watch for banding
AVIF/auto quality 60
auto · q60 loading… balanced default for email
AVIF/auto quality 90
auto · q90 loading… near-lossless — larger payload

Animated source — /cnar/f_auto vs. pg_1

Same animated GIF, three ways: keep the animation, force a single frame, or fall back to GIF for clients without animated WebP.

Animated source preserved
f_auto, animated WebP loading… /cnar/f_auto
Animated source, first frame only
f_gif, first frame only (pg_1) loading… /cnar/f_gif/pg_1
Animated source, GIF fallback
f_gif (full animation) loading… /cnar/f_gif

Email pixel macros — revmail.revcontent.com with JS substitution

ESPs ship pixel impressions with macros like {UNIQUEKEY}, {SENDID}, {DATETIME}, {EMAIL}, {MD5EMAIL}, {SHA1EMAIL}, {SHA256EMAIL}, {ESP}. This demo replaces every macro client-side with a fresh synthetic value on each page load, so refreshing always misses cache and the pixel actually fires through.

creative + click wrapper · cache-busted per pageview loading… resolving macros…

Dynamic template rendering — /template/f_…/?templateId=…&…

Passes arbitrary query-string vars to satori inline-vars mode. templateId is required. Optionally supply url= to override the source image; squish kicks off the source fetch in parallel with the satori call. Supports the same f_ / q_ / w_ transform tokens as /cnar.

Template render with dynamic vars
f_auto, dynamic vars, gif source loading… /template/f_auto/
Template render JPEG, no url param
f_jpeg, source from satori loading… /template/f_jpeg/