Skip to content
Tech Stack19 July 2026 · 7 min readUpdated 30 September 2026

Resend + React Email: Production Transactional Email in 2026

Resend's suppression list spans every subdomain, and React Email's Tailwind support has documented limits. Here is the production setup for both.

Resend + React Email: Production Transactional Email in 2026

You're about to ship password resets, receipts and order confirmations from a SaaS, and you want them to arrive without a second tool for email templates. The first action: pick a dedicated sending subdomain for transactional mail and send one test message to delivered@resend.dev before you write a single template. Everything else in this Resend and React Email setup builds on that.

The idea is simple. Templates become React components in the same repository as your app, reviewed like any other code. The sections below cover sending, styling, the transactional-versus-marketing split and the suppression list, with each fact checked against the vendor's own pages on 2026-09-30.

How do you send a React Email template with Resend?

Four identical interlocking raw concrete panel modules form a single wall panel, split by one glowing cyan seam down the center

Write the template as a React component, then pass it to the react parameter of resend.emails.send() from the Node.js SDK, calling the component as a function rather than as JSX.

Resend's Next.js guide says to pass the component as WelcomeEmail({ name: 'John' }), "not as JSX". The API reference adds that the react parameter is only available in the Node.js SDK, that to accepts a maximum of 50 recipients, and that scheduled_at takes natural language or ISO 8601. React Email itself is MIT licensed, made by Resend, and its render function turns a component into an HTML string for any of 14+ providers. If you use Next.js, the Next.js and Resend stack guide covers the surrounding setup.

For a current baseline, the npm registry shows resend at 6.31.0 and @react-email/components at 1.0.12 as of 2026-09-30. Pin both, because the error below appeared on much older versions.

My recommendation is to keep each template file next to the code that triggers it, so a change to the user object and the email that displays it land in the same pull request and get reviewed together.

A first send, in order:

  1. Install resend and @react-email/components from npm.
  2. Write a small template component with Html, Container, Text and Button.
  3. Verify your transactional subdomain in Resend, as described further down.
  4. Call resend.emails.send() with react: WelcomeEmail({ name: 'Ada' }) and to: ['delivered@resend.dev'].
  5. Check the returned error value and the email's status in the dashboard before you point real users at it.

What does "Objects are not valid as a React child" mean?

It usually means the component reached the SDK in the wrong shape, so check for JSX first. Issue #1803 on resend/react-email reports exactly this message when passing a component to react, and it worked when the reporter passed an HTML string to html instead. The issue was opened in December 2024 with Resend 4.0.1 and @react-email/components 0.0.29, and closed as not planned, so I can't tell you it reproduces on current versions. My reading, which is a hypothesis, is that Resend's function-call guidance is the first fix and rendering to HTML yourself is the fallback.

Idempotency is worth adding here too. The same Next.js guide says idempotency keys must be unique per request and expire after 24 hours, with a suggested pattern of <event-type>/<entity-id>, so a retried job doesn't send a receipt twice. Label each send with tags too, so you can filter by template later; the API reference limits tag keys and values to ASCII letters, numbers, underscores and dashes, up to 256 characters each.

Does Tailwind work in React Email?

A dense grid of thin bone-white bars converges into a narrow concrete channel, with a single bar glowing cyan where it barely fits through

Mostly, using the Tailwind component with a pixel-based preset, and with a short list of unsupported utilities you need to know once. React Email Tailwind questions come up because the limits are documented but easy to miss.

The React Email Tailwind docs state that the component uses tailwindcss 4.1.12, and that pixelBasedPreset switches the styles to a 16px base instead of rem, which suits email clients that handle rem inconsistently. They also list what doesn't work: prose isn't supported, nor are classes that resolve into complex selectors, which is why the space-* utilities fail. Hover styles have limited support. One more detail costs an afternoon if nobody warns you: the docs say a context provider added inside the Tailwind component won't let children call useContext, so put providers outside the wrapper.

Because the library pins its own Tailwind version, expect small differences from your app's Tailwind config. The React Email docs list Gmail, Apple Mail, Outlook, Yahoo! Mail, HEY and Superhuman as the clients it targets, so check your key templates in the ones your customers actually use.

Should transactional and marketing email share one Resend setup?

A concrete form splits into two paths: one fans into many identical ribbed slots, the other narrows to a single slot lit with cyan light

No, keep them separate. Send code-triggered mail such as resets and receipts through single sends on a transactional subdomain, and run campaigns through Broadcasts on another, so a marketing problem can't drag down account mail.

Broadcast APISingle send (emails.send)
TriggerCampaign, manual or scheduledYour code, one message at a time
AudienceA saved contact listAddresses you pass at call time
PersonalizationList-level fieldsFull per-user props in the component
SchedulingNatural language or a timestamp; create-and-send in one call since February 12, 2026scheduled_at or immediate
FitsProduct updates, newslettersPassword resets, receipts, order confirmations

Resend's domain docs recommend sending from "one or more subdomains" instead of the root domain "to isolate your sending reputation", and give an example of keeping tracking on for a newsletter while keeping it off for important transactional mail like password resets. The pricing page reinforces the split: it states marketing plans are limited by contacts, not by emails sent, which matches a Broadcast audience being a contact list while a transactional send targets a single address. Follow this order:

  1. Choose one subdomain per purpose, for example notifications.yourapp.com for transactional and updates.yourapp.com for marketing.
  2. Add each subdomain to Resend and verify the DNS records it shows, one domain at a time.
  3. Turn tracking off for the transactional subdomain and decide separately for marketing.
  4. Send resets, receipts and confirmations only from the transactional address.
  5. Send Broadcasts only from the marketing address.
  6. Watch bounce and complaint rates per subdomain, not as one blended number. That last step is my recommendation.

For the DNS side, the SPF, DKIM and DMARC post goes deeper, and the notification system post covers when email is the wrong channel.

Plan limits are worth knowing before you choose. Resend's pricing page, checked 2026-09-30, lists a Free transactional plan of 3,000 emails a month with a 100-a-day limit, 3 domains and 30-day data retention, Pro from $20 a month for 50,000 emails with no daily limit, and marketing plans priced by contacts rather than emails sent. Pricing changes, so read the page before you budget.

What happens when an address lands on the suppression list?

Resend skips it silently across every domain and subdomain you own, so a subdomain split protects reputation but does not give you separate suppression lists. The suppressions docs say an address is added after a bounce (the recipient's server permanently rejected the message), a complaint (the recipient marked it as spam) or manually, and that it is then "skipped across all your domains and subdomains" for transactional and Broadcast sends alike.

Removal is available from the Suppressions page or the API, including bulk removal of up to 100 addresses at a time. Removing the address without finding out why it bounced only invites the same suppression again, so look at the reason first. That last part is my advice, not Resend's.

How do you test without hurting your reputation?

Use Resend's reserved test addresses. The testing docs list delivered@resend.dev, bounced@resend.dev, complained@resend.dev and suppressed@resend.dev, and recommend them over fake addresses or mock SMTP servers "without damaging your domain reputation". Wire them into your staging tests so the bounce and suppression paths run before real customers hit them.

What do BookBed and Pizzeria Bestek show about email in production?

They show two different uses of the same provider. I can only cite what the case studies say, and neither says which template library was used.

BookBed, a Flutter, Firebase and Stripe product, ships eighteen-plus Resend email templates alongside email verification, according to its case study. Pizzeria Bestek, a React and Supabase build, uses email as its admin interface. The owner opens a new-order email and clicks CONFIRM or DECLINE, and three Supabase Edge Functions handle the rest. Every template has four language variants, and pickup and delivery declines use different templates because the suggested alternative differs. The restaurant received Supabase, Netlify and Resend credentials on handover.

I'm not claiming that either one uses React Email; the case studies don't say, so that stays out of this post. Neither project needed a dedicated email team. Each needed templates that were easy to change and mail that stayed deliverable. If you're still choosing the rest of your SaaS MVP stack, settle it before your email provider, since email is one of the last pieces to bolt on.

Open the from-address on your own password-reset email now. Is it on a subdomain that has never sent a marketing campaign?

Free resource

Free SaaS MVP Scope Template

A Notion document with the full feature checklist, MVP vs. nice-to-have table, pre-build questions, and cost signals — so you walk into any developer call knowing exactly what to ask for.

Get the template →
DL

Dusko Licanin

Full-Stack Developer · Banja Luka, Bosnia

Full-stack developer shipping SaaS MVPs, web apps, and mobile apps using AI-augmented workflows — without agency coordination overhead. Live portfolio: BookBed, Callidus, Pizzeria Bestek.

Frequently Asked Questions

What are React Email components?

They are typed React components that render to email-safe HTML, so you write templates the way you write any other UI. React Email's docs list building blocks such as Html, Container, Button and Text, and a render function that converts a component to an HTML string for providers including Resend, Nodemailer, SendGrid and AWS SES. The project is MIT licensed and made by Resend. With Resend's Node.js SDK you can pass the component directly to the react parameter, calling it as a function rather than as JSX.

Is Resend good for transactional email?

Yes, for teams that want a code-first API and a clear split between transactional sends and marketing Broadcasts. Its pricing page, checked 2026-09-30, lists a Free transactional plan of 3,000 emails a month with a 100-a-day limit and 3 domains, and Pro from $20 a month for 50,000 emails with no daily limit. Marketing plans are priced by contacts, not emails sent. Prices change, so confirm on the pricing page, and test with the reserved resend.dev addresses before real customers receive anything.

How do I build SaaS email templates with Resend and React?

Write each template as a React component in your app's repository, install resend and @react-email/components, and call resend.emails.send with the component in the react parameter. Resend's docs say to pass it as a function call, such as WelcomeEmail({ name: 'John' }), not as JSX. Send transactional mail from a dedicated subdomain, add an idempotency key so retries do not duplicate messages, and test with delivered@resend.dev before you connect real addresses.

Does Tailwind CSS work with React Email?

Mostly, through the Tailwind component, which the docs say uses tailwindcss 4.1.12. Use pixelBasedPreset so styles use a 16px base instead of rem. The docs state that prose classes and utilities that resolve into complex selectors, including space utilities, are not supported, and hover styles have limited support. Put any context provider outside the Tailwind component, because a provider inside it will not let children call useContext. Check your key templates in the email clients your customers use.

What happens if an email address ends up on Resend's suppression list?

Resend skips it silently, so sends to that address never go out. The docs say an address is added after a bounce, a complaint or a manual entry, and that suppressed addresses are skipped across all your domains and subdomains for both transactional and Broadcast sends. You can remove an address on the Suppressions page or through the API, including bulk removal of up to 100 at a time. Look at why it was suppressed before removing it, because a hard bounce with the same cause will usually suppress it again.