Tooling · 2026
Heddlemail
A WYSIWYG email builder that refuses to send anything its preview did not show.
- Role
- Design and build
- Timeline
- 2026
- Stack
- TypeScript, React, Zod, Vitest
- Links
- Live site ↗ · 2 min read

The problem
The previous email builder had the worst kind of bug: the preview looked perfect, the email went out, and part of it was missing. Nested content simply vanished from what was sent. No error, no warning — just quietly wrong emails reaching real inboxes.
A builder whose preview cannot be trusted is worse than no builder. So this was a rebuild around one guarantee: what renders on screen is what ships.
Finding the cause
I traced the vanishing content to the exporter. When it met a structure it did not handle, it did not fail — it returned empty output and carried on. Every unhandled case became silent data loss.
What I built
A compiler that refuses rather than guesses
The export step is now a compiler with a strict contract: if it cannot faithfully produce a piece of the template, it refuses to emit and says why. A loud failure in the editor is cheap. A silent one in a customer's inbox is not.
Inputs are validated with Zod at the boundary, so malformed templates are caught before they reach the compiler at all.
One code path for preview and export
The root cause of the drift was that preview and export were two different pieces of code doing "the same thing". Now they are the same code path. The preview is the compiled output, so the two cannot disagree.
Every template is a test
Every template is wired into the Vitest suite. If the compiled output of any template changes unexpectedly, the build fails, and nothing ships until someone looks at the difference and accepts it.