mrkeyoor.com_
Sat 08 Aug 22:49 UTC
npmWeb Frontendupdated 08 Aug 2026

react-email

React Email 6 is a React and TypeScript toolkit for building email markup from components, rendering those components to HTML or plain text at send time, and previewing templates in a local browser. The package now contains the layout components, Tailwind integration, rendering utilities, and the email CLI that older versions split across several @react-email packages. It helps with table-oriented email structure and known client quirks, but it is not an email delivery service and does not make browsers and inbox clients behave alike.

Verdict

The strongest React-native email authoring stack when templates are real application code and the team will test in actual inboxes. It is excessive for sending existing HTML, and version 6 deserves a deliberate migration because package imports, Node support, and CLI behavior changed.

API stability3/5The component model is familiar and typed, but the project still makes meaningful major-version changes. Version 6 moved components and rendering utilities from @react-email/components and @react-email/render into react-email, raised the effective setup around Node 20, and continues to adjust Tailwind behavior and CLI flags. The changelog is clear, yet upgrades can touch imports, generated output, styling, and preview deployment rather than only package versions.
Docs4/5The official site covers components, rendering, CLI commands, providers, deployment, Tailwind, and many copyable templates. The CLI documentation honestly says export is secondary to rendering with real props at send time and warns that preview static assets are not hosted. Some pages lag the implementation: the build page still lists --packageManager even though current source and the 6.1.4 changelog say that option is deprecated and ignored.
Maintenance5/5Version 6.9.2 was published on August 7, 2026, and the repository was pushed again on August 8. Recent 6.x notes include fixes for Tailwind 4.3 changes, preview path traversal protection, monorepo builds, Outlook CSS, large export memory use, and static asset filenames. GitHub reports 27 open issues and pull requests in a repository with 19,576 stars, evidence of active release and review work rather than a dormant template set.
Ecosystem5/5The package recorded 3,313,334 downloads in the measured week, supports React 18 and 19, and documents integrations with Resend, Nodemailer, SendGrid, Mailgun, Postmark, SES, Azure, and other senders. Templates render to ordinary HTML and plain text, so delivery is provider-neutral. The main limitation is ecosystem weight: the package has 22 runtime dependencies and the full measured bundle is 503.5 KB gzipped.

Use it if

  • Your team already uses React and wants transactional email templates to accept typed props like application UI
  • You want a local preview with hot reload, editable preview props, and compatibility warnings for major email clients
  • You need to render HTML and plain text at send time, then hand both outputs to Resend, Nodemailer, SES, or another provider
  • You maintain enough templates that shared components, Tailwind classes, and automated HTML export are worth a dedicated toolchain
Skip it if

Setup reality

Install react-email plus compatible React and React DOM peers, then use Node 20 or newer. Version 6 changed the package boundary: components and render utilities are exported from react-email itself, so current examples should not begin by adding @react-email/components and @react-email/render separately. The CLI expects ./emails by default, finds .js, .jsx, and .tsx files with a default export, and recursively treats them as templates; prefix shared directories with an underscore to keep them out of the sidebar. email dev starts on port 3000 and serves emails/static for previews, but those files are not hosted for recipients. Production image URLs must be absolute and publicly reachable. PreviewProps supplies fake data in the UI, while real sends must pass validated application data to the component. email export is secondary to render-at-send-time and deletes an existing output directory before rebuilding it, so never point --outDir at a directory containing hand-edited files. Plain-text export, pretty HTML, and custom extensions are separate flags. email build copies a deployable preview app into .react-email, removes any existing folder there, installs its dependencies with npm, and email start fails until that build exists. The old --packageManager build option is now hidden, deprecated, and ignored even though older documentation may still show it. No provider credentials are needed to author, preview, render, or export. Sending still needs a separate transport and its API key or SMTP configuration. The optional email resend setup command stores a Resend API key in user-level configuration, which is unrelated to rendering templates. Tailwind styles are converted and sanitized for email, but unsupported CSS does not become universally safe; keep Head inside Tailwind when using classes that produce media rules, and verify output in actual target clients.

Patterns

Create a typed email templatecreate-email-template

import {Body, Button, Container, Head, Html, Preview, Text} from 'react-email';

type WelcomeProps = {name: string; verifyUrl: string};

export default function WelcomeEmail({name, verifyUrl}: WelcomeProps) {
  return (
    <Html lang="en">
      <Head />
      <Preview>Confirm your new account</Preview>
      <Body style={{backgroundColor: '#f6f6f6', fontFamily: 'Arial, sans-serif'}}>
        <Container style={{backgroundColor: '#ffffff', padding: '24px'}}>
          <Text>Hello {name},</Text>
          <Button href={verifyUrl} style={{backgroundColor: '#111827', color: '#ffffff', padding: '12px 18px'}}>
            Verify account
          </Button>
        </Container>
      </Body>
    </Html>
  );
}

Version 6 exports components directly from react-email. Pass only trusted, validated URLs and user data into the template.

Supply sample data to the preview UIset-preview-props

type ReceiptProps = {customer: string; total: string};

function Receipt({customer, total}: ReceiptProps) {
  return <Text>{customer}, your total is {total}.</Text>;
}

Receipt.PreviewProps = {
  customer: 'Ada',
  total: '$42.00',
} as ReceiptProps;

export default Receipt;

PreviewProps is development sample data, not a runtime default or validation layer. Real sends must pass their own props.

Run previews from a custom template directoryrun-preview-server

npx react-email dev --dir ./src/emails --port 3001 --clients outlook,gmail

The default directory is ./emails and the default port is 3000. The clients flag narrows compatibility warnings; it does not emulate those inboxes.

Keep shared files out of the template sidebarhide-shared-components

emails/
  _components/
    email-footer.tsx
  account-created.tsx
  password-reset.tsx
  static/
    logo.png

The CLI recursively discovers default-exported .js, .jsx, and .tsx files. Prefix a directory with an underscore when its files are helpers, not templates.

Inline Tailwind styles for emailstyle-with-tailwind

import {Body, Head, Html, Tailwind, Text} from 'react-email';

export default function Notice() {
  return (
    <Html>
      <Tailwind>
        <Head />
        <Body className="bg-white p-6">
          <Text className="text-base leading-6 text-slate-900">Payment received</Text>
        </Body>
      </Tailwind>
    </Html>
  );
}

Keep Head inside Tailwind when classes generate media queries or other non-inline rules; the current component throws when it has nowhere to place them.

Switch preview assets to a hosted production URLuse-production-images

import {Img} from 'react-email';

const assetBase = process.env.NODE_ENV === 'production'
  ? 'https://cdn.example.com'
  : '';

export function Logo() {
  return <Img src={`${assetBase}/static/logo.png`} width="160" height="48" alt="Example" />;
}

emails/static is served only by the local preview. A relative /static URL will not load for recipients unless your sending environment rewrites or hosts it.

Render HTML at send timerender-html

import {render} from 'react-email';
import WelcomeEmail from './emails/welcome-email';

const html = await render(
  <WelcomeEmail name={user.name} verifyUrl={verifyUrl} />,
);

render is asynchronous in version 6. Rendering with the real props at send time is the documented primary path.

Render a plain-text alternativerender-plain-text

import {render} from 'react-email';

const text = await render(
  <WelcomeEmail name={user.name} verifyUrl={verifyUrl} />,
  {plainText: true},
);

Generate both HTML and text for delivery. Plain-text conversion is derived from the rendered markup, so inspect links, headings, and spacing in the result.

Send rendered output through Nodemailersend-with-nodemailer

const element = <WelcomeEmail name={user.name} verifyUrl={verifyUrl} />;
const [html, text] = await Promise.all([
  render(element),
  render(element, {plainText: true}),
]);

await transporter.sendMail({
  from: 'Example <hello@example.com>',
  to: user.email,
  subject: 'Confirm your account',
  html,
  text,
});

react-email renders content but does not deliver it. Configure, authenticate, retry, and monitor the transport separately.

Export templates as readable HTML filesexport-static-html

npx react-email export --dir ./emails --outDir ./generated-emails --pretty

The exporter removes an existing output directory before writing. Keep generated-emails dedicated to generated artifacts and out of any hand-maintained tree.

Export plain text or a custom extensionexport-plain-text

npx react-email export --dir ./emails --outDir ./text-emails --plainText

npx react-email export --dir ./emails --outDir ./shopify-emails --extension blade.php

Export has no real recipient props unless they are encoded in the template. The docs recommend it mainly for non-JavaScript backends or platforms that require manual templating.

Build and start the preview applicationdeploy-preview-app

npx react-email build --dir ./emails
npx react-email start

build recreates .react-email and installs the preview app dependencies with npm. start requires that folder, so this is heavier than exporting email HTML.

Alternatives

PackageRegistryPick it when
mjmlnpmYou want a purpose-built email markup language and compiler without React component semantics
@maizzle/frameworknpmYou prefer HTML, Tailwind CSS, layouts, and a static build pipeline for email campaigns
email-templatesnpmA Node service needs template rendering, localization hooks, previews, and delivery in one older-style workflow
nodemailernpmYou already have HTML and plain text and only need a mature SMTP transport