emlet
← Back to blog

Engineering

How to Send HTML Emails From a React App Without Losing Your Mind

Aarya, Founder of Emlet·July 3, 2026·9 min read
Close-up of colorful code on a computer screen

You've built the whole product in React. Components, hooks, a design system, the works. Then someone asks for a "welcome email" and you go looking for the equivalent, and there isn't one. You can't just render your React app to a string and mail it, because email clients don't run JavaScript, don't load external stylesheets, and half of them (looking at you, Outlook) render HTML with a rendering engine borrowed from a word processor. Everything you know about building UI in React quietly stops applying.

Why you can't just reuse your components

Modern web layout leans on flexbox, grid, external CSS, media queries, custom fonts loaded via @font-face, and JavaScript for anything interactive. Email HTML supports approximately none of that reliably. No grid. Flexbox support is inconsistent at best. No external stylesheets, styles have to be inlined on every element, because plenty of clients strip style blocks out of the document head entirely. No JS, obviously, an email is not a web page with a script tag. The safe baseline is still table-based layout with inline styles, the exact thing web development spent the 2010s trying to leave behind, because it's genuinely the one approach that survives Outlook's Word rendering engine and everything else at the same time.

What React Email actually does

React Email is an open source component library that gives you a familiar JSX API, `Section`, `Row`, `Column`, `Text`, `Button`, `Img`, but compiles it down to that same defensive, table-based, inline-styled HTML under the hood. You write something like:

<Section style={{ padding: '32px 24px' }}>
  <Row>
    <Column>
      <Text style={{ fontSize: 24, fontWeight: 700, color: '#111' }}>
        Welcome to the team
      </Text>
      <Button
        href="https://example.com/get-started"
        style={{ background: '#00c2c2', color: '#fff', padding: '12px 24px' }}
      >
        Get started
      </Button>
    </Column>
  </Row>
</Section>

and it renders to real nested tables with inline styles, the exact markup you'd otherwise have to hand-write and re-test in every client yourself. You get version control, code review, and reusable components for something that used to live in a designer's Litmus account as a one-off HTML file nobody wanted to touch.

The actual workflow

In practice, you render the React Email component to an HTML string server-side (there's a `render()` helper for exactly this), and hand that string to a transactional sending provider, Resend, Postmark, SES, whichever you're already using. React Email doesn't send anything itself, it solves the templating half of the problem, not delivery. Resend in particular was built by the same team and integrates directly, but the rendered HTML works with any provider that accepts raw HTML.

Where it still gets annoying

This solves the transactional case well, password resets, receipts, "your order shipped." It gets messier for marketing emails specifically, for a few reasons:

  • Marketing copy changes constantly, and per-campaign edits to a JSX component mean either a deploy or a non-technical teammate opening your codebase, neither of which is realistic day to day.
  • Brand consistency (colors, logo placement, tone) has to be manually maintained across every component you write, there's no built-in concept of "brand" the way a design tool has a shared style library.
  • Testing across clients, Gmail, Outlook, Apple Mail, dark mode, is still on you. React Email gives you safer defaults, not a guarantee.

I've written more on the specific rendering failures that show up even with correct-looking HTML in this post, if you want the client-by-client breakdown.

Where this is heading

The honest answer for a lot of teams is a split workflow: engineering owns the transactional templates in code, because those need to live alongside the app and ship with deploys, and marketing needs something faster for campaigns that doesn't route through a pull request. That's the gap Emlet fills on the marketing side, it generates the same kind of table-based, brand-consistent HTML (and exports the equivalent TSX if you want to hand it back to engineering), from a plain English description instead of hand-written JSX. Engineers get a starting point without spending an afternoon on it, marketers get something they can actually edit without opening an IDE.

Get a starting point in seconds

Describe the email, get back production HTML and TSX you can hand to your team or drop straight into your sending pipeline.

Generate your first email free