Nudge Blocks · email render service

Email-ready visual blocks, behind one API.

Small JSON or query-string configs turn into hosted GIF / PNG / JPG that Nudge's AI marketer drops straight into emails as plain <img>. Every block exists because Gmail and Outlook strip CSS animation — pixels are the only thing that works everywhere.

2 of 3 blocks live FastAPI · Pillow · Playwright Railway · /data volume

Available blocks

The blocks

Each block is one route. Click into a card for the full integration brief — params, samples, embed snippet, email-client gotchas.

Announcement Bar

Live
Scrolling announcement bar preview

A right-to-left scrolling offer bar — "FREE SHIPPING · USE CODE SAVE20 · ENDS SUNDAY". Deterministic, so identical configs reuse the same hosted GIF across a campaign.

POST /api/v1/announcement-bar cached by config ~170–460 KB
View docs v0.1

Countdown

Live
Live countdown preview

A ticking days / hours / minutes / seconds GIF to a target moment. Time-relative — every email open re-hits the endpoint for the current value, so the URL is the image.

GET /api/v1/countdown.gif per open · no-store ~12–25 KB
View docs v0.1 · boxed / plain / flip

HTML to Image

Planned
Renderer stub + design notes in app/blocks/html_image/
Spec: docs/blocks/html-to-image.md

Headless-Chromium renderer (Playwright) for layouts CSS can't express in email — anything from a styled receipt to a chart. Caller HTML is untrusted, so the sandbox / egress story is the first thing the build will lock down. Heavier deps than the Pillow blocks, so it builds from its own Dockerfile.

POST /api/v1/html-image cached by config Playwright · Chromium
Not yet built spec only

Shared architecture

Why everything renders to images

Email clients are the whole reason this service exists. Gmail, Outlook desktop, and most major clients strip <style> blocks, ignore @keyframes, don't honor <marquee>, and drop most modern CSS. The two things that work almost everywhere are an animated GIF and a static raster image.

Config → pixels → URL

Every block has the same shape: a small JSON or query-string config in, hosted image URL out. The email gets a plain <img>.

Deterministic vs time-relative

Deterministic blocks (announcement bar, html-image) hash the config and reuse the same GIF across a blast. The countdown is per-open and never cached.

Fonts baked into pixels

Recipients don't have our fonts, so we render with bundled .ttfs. There is no "use the system font" — only glyphs present in the chosen font render.