Back to Articles
React
Email
Architecture
TypeScript

How I Simplified My Email System by Moving Templates to React

January 10, 20253 min read

Why backend-owned HTML emails did not scale for us, and how moving to React Email with generated types fixed it.


I recently refactored how we build and send transactional emails, and the result surprised me by how much friction it removed across the team.

This post is about why backend-owned HTML emails did not scale for us, and how moving to React Email with generated types fixed it.

The Original Problem

Our email templates were written directly in the backend using raw HTML and CSS.

That created a few issues:

  • Frontend engineers had to clone the backend repo just to update email UI
  • Backend engineers were forced to write and maintain HTML and CSS, which is neither safe nor enjoyable
  • Changes required tight coordination and context switching
  • Velocity slowed as the system grew

We considered using our email provider's template engine (SendPulse) and generating templates there, then passing template IDs to the backend.

That introduced new problems:

  • A wrong template ID breaks email sending entirely
  • Debugging failures became harder
  • Writing and maintaining templates inside the provider UI was time consuming
  • The system felt fragile and stressful

None of this scaled well as the team and product evolved.

The New Approach

Instead of fighting the problem, I stepped back and asked a simple question:

Why are emails not treated like UI?

So I changed the model entirely.

We now build emails using React Email, just like frontend components.

Here is the high-level setup:

  • Emails live in their own repository
  • Each email is a React Email component
  • Variables are strongly typed
  • HTML and text versions are generated on demand
  • Backend never touches UI or markup

To make this smooth, I added a few things:

  • A Plop generator to scaffold new email templates instantly
  • A script that auto-generates TypeScript types for each template
  • A CI flow that builds and publishes the templates as a private package
  • A small serverless function that renders HTML and text on request

Deployment stays fast (under a minute) using caching, and updates are safe and predictable.

The "Oh Wow" Moment

The biggest win was the separation of concerns.

  • Frontend owns email UI, content, and expected props
  • Backend only knows what data to send, enforced by types
  • No one needs to understand the other side's codebase
  • No more guessing template variables
  • No more broken emails due to mismatched IDs or missing fields

The backend installs the email package and updates it only when needed. If the types are wrong, they instantly know.

That shift alone removed an entire class of bugs and team friction.

Why This Scales Better

This approach is:

  • Safer, because types enforce correctness
  • Faster, because templates are generated and shared automatically
  • Cheaper, because we are not locked into provider-specific template tooling
  • More enjoyable, because everyone works in their area of strength

Most importantly, it scales with team velocity.

What Past Me Should Have Known

Backend-owned HTML emails do not scale with growing teams.

Emails are UI. Treat them like UI, version them like code, type them like APIs, and suddenly the whole system becomes calmer.

If you are feeling friction around email templates today, it is probably not a tooling issue. It is an ownership and architecture issue.


Find the repo here: react-email-template-bootstrap

Enjoyed this article?

Let's connect and discuss more about frontend architecture and AI engineering.