Cross-client HTML email

html-email

A hand-authored, zero-dependency framework built on one principle: never drop support for the oldest clients. Every conditional comment, MSO hack, and VML fallback is documented and linted.

See it render

Open, download, or copy the actual email HTML. Both preserve the full cross-client compatibility engineering.

Framework build → The assembled output from framework/ partials, populated with the Northwind Botanicals winter-arrivals campaign.
Open Download
2014 reference campaign → A production template from 2014, content-scrubbed to a fictitious brand, compatibility engineering byte-preserved.
Open Download

Branded templates

Five distinct designs, each rebuilt in the house conventions with a fictitious brand and self-authored generated art. Copy the HTML straight into your ESP, or download it to edit.

Previews

Rendered from the framework build via headless Chrome.

Desktop, light mode
Desktop · light
Desktop, dark mode
Desktop · dark
Mobile, single column
Mobile · stacked

Lint your own email

The linter is zero-dependency and works on any HTML email, whatever built it — MJML, React Email, Maizzle, or hand-written. The default rule set is client behaviour every email is subject to, not this project's conventions.

node framework/build/lint.mjs campaign.html

It checks Gmail's 102 KB clip and 8 KB <style> cap, unbalanced CSS, missing alt/width, MSO conditional balance, the unsubscribe link, and more — with --json and --sarif output for CI.

Build it yourself

Zero dependencies. Assemble the partials and lint the output:

cd framework/build && node build.mjs && node lint.mjs --profile house ../dist/email.html

View on GitHub Pre-send checklist →