Sendbound
React Email

Write emails like you write UI — with React

Build dynamic, type-safe, version-controlled email templates with the component model your team already knows. Hot-reload preview, Outlook-compatible output, and one-line sending.

Component-driven email
welcome-email.tsx
import { Html, Body, Heading, Text, Button } from '@react-email/components';

interface WelcomeEmailProps {
  name: string;
  plan: 'free' | 'pro' | 'enterprise';
}

export default function WelcomeEmail({ name, plan }: WelcomeEmailProps) {
  return (
    <Html>
      <Body>
        <Heading>Welcome, {name}!</Heading>
        <Text>You are on the <strong>{plan}</strong> plan.</Text>
        {plan === 'free' && (
          <Text>Upgrade anytime to unlock unlimited sends.</Text>
        )}
        <Button href="https://app.sendbound.com">
          Get started
        </Button>
      </Body>
    </Html>
  );
}

React primitives

Html, Body, Heading, Text, Button — all render to email-safe HTML.

Learn more

Typed props

Missing a required prop is a compile error, not a runtime bug.

Learn more

Version controlled

Review every template change in Git, the same as any other code.

Learn more

100%

TypeScript — no implicit any in your templates

<100ms

Hot-reload preview in the browser

50+

Email clients tested in preview mode

0

HTML you need to write or maintain

TypeScript first

TypeScript first

Full type safety for every component, prop, and style. Catch errors before they reach production — a missing required prop or a typo in a URL is a compile error, not a support ticket at 2am.

  • Typed props for all @react-email/components primitives
  • IntelliSense autocomplete in VS Code and Cursor
  • Zod schemas for template input validation
  • Strict mode compatible — no implicit any
Type check passed ✓
Live preview without deploying

Live preview without deploying

See your email rendered in real time as you type. The preview server hot-reloads on every save and renders across Gmail, Outlook, and Apple Mail simultaneously — no test sends required until you are ready.

  • Hot-reload preview in the browser on every file save
  • Toggle between desktop and mobile viewport
  • Preview with real prop values via the props panel
  • Send a test email to your inbox in one click
Preview updated instantly
Workflow

From component to inbox in 4 steps

Write once in your editor. Preview in the browser. Ship to any inbox.

01

Write

Create a .tsx file. Import Html, Body, Heading, Text, Button from @react-email/components. Use any React pattern — conditionals, loops, shared layouts, sub-components.

02

Preview

Run the preview server. Your browser shows the email rendered in real time. Change a prop in the panel; the preview updates instantly. No build step, no test send needed.

03

Test

Click "Send test" to deliver the email to your own inbox. Inspect the real rendered HTML, check headers, and verify rendering across clients before touching production.

04

Send

Pass your component to sb.emails.send({ react: <YourTemplate props={...} /> }). Props are type-checked at compile time. Sendbound renders it to HTML and delivers it.

Code examples

Every pattern you need, covered

Dynamic lists, conditional content, shared layouts — all the patterns that are painful in HTML or MJML are natural in JSX.

Sending a React template

import { Sendbound } from '@sendbound/node';
import { WelcomeEmail } from './emails/welcome';

const sb = new Sendbound({ apiKey: process.env.SENDBOUND_KEY });

await sb.emails.send({
  from: 'Acme <hello@acme.com>',
  to: user.email,
  subject: 'Welcome to Acme, ' + user.name + '!',
  react: <WelcomeEmail name={user.name} plan={user.plan} />,
});
// Props are type-checked at compile time.
// Missing a required prop is a build error, not a runtime crash.

Dynamic lists (invoice line items)

import { Html, Body, Section, Row, Column } from '@react-email/components';

interface InvoiceEmailProps {
  items: { description: string; amount: number }[];
  total: number;
}

export default function InvoiceEmail({ items, total }: InvoiceEmailProps) {
  return (
    <Html><Body>
      <Section>
        {items.map((item, i) => (
          <Row key={i}>
            <Column>{item.description}</Column>
            <Column>{item.amount.toFixed(2)}</Column>
          </Row>
        ))}
        <Row><Column>Total</Column><Column>{total.toFixed(2)}</Column></Row>
      </Section>
    </Body></Html>
  );
}
Use cases

The right tool for every email type

React Email works equally well for transactional triggers, marketing sequences, and internal notifications.

Transactional emails

Receipts, invoices, password resets, shipping notifications. TypeScript props guarantee every required field — order total, reset link, tracking number — is present at compile time, not discovered by a user who gets a blank email.

Onboarding sequences

Personalized welcome flows where content varies by user plan, role, or feature usage. Shared layout components keep branding consistent across all 12 steps of your sequence without copy-pasting.

Internal digests & alerts

Weekly usage digests, error alerts, and team notifications generated from your backend. Complex conditional logic and dynamic lists that would be unmaintainable in Handlebars are clean JSX.

How we compare

React Email vs the alternatives

MJML, raw HTML, and Handlebars all have their place. Here is how they compare for teams shipping product emails.

FeatureReact EmailMJMLRaw HTMLHandlebars
Type safety (TypeScript props)✓✗✗✗
Hot-reload browser preview✓Partial✗✗
Version control friendly✓✓✓✓
Component reuse / shared layouts✓Partial✗Partial
Conditional logic (if/else)✓✗✗✓
Dynamic lists (map / repeat)✓✗✗✓
Outlook 2007+ compatible output✓✓PartialPartial
Tailwind CSS support✓✗✗✗

React Email questions, answered

Do I need to know React to use this?

Yes, basic React knowledge is required for React Email templates. If your team does not use React, Sendbound also supports plain HTML templates and MJML — you can mix template types in the same project. React Email is the recommended approach for teams who already use React in their frontend or backend.

Does React Email support Tailwind CSS?

Yes. Wrap your component with the @react-email/tailwind component and all Tailwind utility classes are compiled to inline styles at send time. This means your email renders correctly even in clients like Outlook that strip <style> blocks.

How does Outlook rendering work?

React Email renders your components to table-based HTML that is compatible with Outlook 2007, 2010, 2013, 2016, and 365. The component library is designed to avoid CSS properties that Outlook ignores. The preview mode shows an Outlook-accurate render so you can catch issues before sending.

Can I use React Server Components?

No. React Email uses standard React (not RSC). Templates are rendered server-side by calling the render() function, which returns an HTML string. You can call render() from any Node.js environment — Express, Next.js API routes, workers, or a standalone script.

How do I preview templates with real data?

The preview server lets you define named "story" prop sets in a .stories.ts file alongside your template. Switch between stories in the browser to see how the template renders with different data — empty arrays, long strings, missing optional fields — without sending a test email each time.

Is there a limit on template complexity?

No. Templates are just React components. You can import shared components, use context, call utility functions, and structure your code exactly as you would any other React project. The only constraint is that templates must be renderable to a static HTML string — no browser APIs, no useEffect.

What version of React is required?

React 18+ is required for React Email. All @react-email/components are compatible with React 18 and the rendering pipeline uses react-dom/server.

Can I test templates in CI/CD?

Yes. Call render(<YourTemplate props={...} />) in a test and snapshot the HTML output. Combine with jest or vitest to catch unintended template changes before they ship. Sendbound also provides a template linter that flags common deliverability issues as part of the build.