Claude Code for React Email: Transactional Email Templates in React — Claude Skills 360 Blog
Blog / Backend / Claude Code for React Email: Transactional Email Templates in React
Backend

Claude Code for React Email: Transactional Email Templates in React

Published: February 18, 2027
Read time: 7 min read
By: Claude Skills 360

React Email builds transactional email templates using React components. The @react-email/components package provides email-compatible primitives — Html, Head, Body, Section, Row, Column, Button, Text, and Img — that render to inbox-compatible HTML with correct inline styles. render(Template, props) converts a React component to an HTML string and optional plain-text fallback. The React Email CLI starts a local preview server showing templates across email client previews. @react-email/tailwind applies Tailwind classes as inline styles automatically. Resend, SendGrid, Postmark, and Nodemailer accept the rendered HTML string directly. Claude Code generates React Email templates for order confirmations, shipping notifications, password resets, and drip sequence emails with cross-client compatible markup.

CLAUDE.md for React Email

## React Email Stack
- Version: @react-email/components >= 0.0.22, react-email >= 3.0
- Render: render(Template, props) → HTML string — pass to email provider
- Layout: Html > Head > Preview > Body > Container > Section > Row > Column
- Tailwind: <Tailwind config={theme}> wrapper — converts tw classes to inline styles
- Preview: npx react-email dev — live preview at localhost:3000
- Test: npx react-email export — exports HTML for email client testing
- Send: Resend, SendGrid, Nodemailer — all accept HTML string from render()

Order Confirmation Template

// emails/order-confirmation.tsx — React Email template
import {
  Html,
  Head,
  Preview,
  Body,
  Container,
  Section,
  Row,
  Column,
  Text,
  Button,
  Img,
  Hr,
  Link,
} from "@react-email/components"
import { Tailwind } from "@react-email/tailwind"

interface OrderConfirmationProps {
  customerName: string
  orderId: string
  orderUrl: string
  items: {
    name: string
    quantity: number
    priceCents: number
    imageUrl?: string
  }[]
  subtotalCents: number
  shippingCents: number
  totalCents: number
  estimatedDelivery: string
  shippingAddress: {
    line1: string
    city: string
    country: string
  }
}

export function OrderConfirmation({
  customerName,
  orderId,
  orderUrl,
  items,
  subtotalCents,
  shippingCents,
  totalCents,
  estimatedDelivery,
  shippingAddress,
}: OrderConfirmationProps) {
  return (
    <Html>
      <Head />
      <Preview>Order #{orderId.slice(-8)} confirmed — estimated delivery {estimatedDelivery}</Preview>
      <Tailwind>
        <Body className="bg-gray-50 font-sans">
          <Container className="mx-auto py-8 px-4 max-w-xl">

            {/* Header */}
            <Section className="text-center mb-8">
              <Img
                src="https://example.com/logo.png"
                width="140"
                height="40"
                alt="MyStore"
                className="mx-auto"
              />
            </Section>

            {/* Confirmation */}
            <Section className="bg-white rounded-lg p-8 mb-6 shadow-sm">
              <Text className="text-2xl font-bold text-gray-900 mb-2">
                Order Confirmed!
              </Text>
              <Text className="text-gray-500 text-sm mb-6">
                Hi {customerName}, thanks for your order. We'll notify you when it ships.
              </Text>

              <Row>
                <Column>
                  <Text className="text-xs text-gray-400 uppercase">Order Number</Text>
                  <Text className="text-sm font-medium text-gray-900">
                    #{orderId.slice(-8)}
                  </Text>
                </Column>
                <Column>
                  <Text className="text-xs text-gray-400 uppercase">Est. Delivery</Text>
                  <Text className="text-sm font-medium text-gray-900">
                    {estimatedDelivery}
                  </Text>
                </Column>
                <Column>
                  <Text className="text-xs text-gray-400 uppercase">Ship To</Text>
                  <Text className="text-sm font-medium text-gray-900">
                    {shippingAddress.city}, {shippingAddress.country}
                  </Text>
                </Column>
              </Row>

              <Button
                href={orderUrl}
                className="bg-blue-600 text-white px-6 py-3 rounded-md text-sm font-medium mt-6 block text-center"
              >
                View Order Details
              </Button>
            </Section>

            {/* Order Items */}
            <Section className="bg-white rounded-lg p-6 mb-6 shadow-sm">
              <Text className="font-semibold text-gray-900 mb-4">Order Summary</Text>

              {items.map((item, i) => (
                <Row key={i} className="mb-4">
                  {item.imageUrl && (
                    <Column className="w-16 pr-4">
                      <Img
                        src={item.imageUrl}
                        width="48"
                        height="48"
                        alt={item.name}
                        className="rounded"
                      />
                    </Column>
                  )}
                  <Column>
                    <Text className="text-sm font-medium text-gray-900 mb-0">
                      {item.name}
                    </Text>
                    <Text className="text-xs text-gray-500 mt-0">
                      Qty: {item.quantity}
                    </Text>
                  </Column>
                  <Column className="text-right">
                    <Text className="text-sm text-gray-900">
                      ${((item.priceCents * item.quantity) / 100).toFixed(2)}
                    </Text>
                  </Column>
                </Row>
              ))}

              <Hr className="my-4 border-gray-200" />

              <Row>
                <Column><Text className="text-sm text-gray-500">Subtotal</Text></Column>
                <Column className="text-right">
                  <Text className="text-sm text-gray-900">${(subtotalCents / 100).toFixed(2)}</Text>
                </Column>
              </Row>
              <Row>
                <Column><Text className="text-sm text-gray-500">Shipping</Text></Column>
                <Column className="text-right">
                  <Text className="text-sm text-gray-900">
                    {shippingCents === 0 ? "Free" : `$${(shippingCents / 100).toFixed(2)}`}
                  </Text>
                </Column>
              </Row>
              <Row>
                <Column><Text className="text-base font-bold text-gray-900">Total</Text></Column>
                <Column className="text-right">
                  <Text className="text-base font-bold text-gray-900">${(totalCents / 100).toFixed(2)}</Text>
                </Column>
              </Row>
            </Section>

            {/* Footer */}
            <Section className="text-center">
              <Text className="text-xs text-gray-400">
                Questions? <Link href="mailto:[email protected]" className="text-blue-600">[email protected]</Link>
              </Text>
              <Text className="text-xs text-gray-400">
                123 Main St, San Francisco, CA 94102
              </Text>
            </Section>

          </Container>
        </Body>
      </Tailwind>
    </Html>
  )
}

// Default props for preview
OrderConfirmation.PreviewProps = {
  customerName: "Alice Smith",
  orderId: "ord-abc123def456",
  orderUrl: "https://example.com/orders/ord-abc123def456",
  items: [
    { name: "Widget Pro", quantity: 1, priceCents: 2999 },
    { name: "Widget Basic", quantity: 2, priceCents: 999 },
  ],
  subtotalCents: 4997,
  shippingCents: 0,
  totalCents: 4997,
  estimatedDelivery: "Jan 25–28",
  shippingAddress: { line1: "123 Main St", city: "San Francisco", country: "US" },
} satisfies OrderConfirmationProps

export default OrderConfirmation

Sending with Resend

// lib/email.ts — render and send with Resend
import { Resend } from "resend"
import { render } from "@react-email/render"
import { OrderConfirmation } from "./emails/order-confirmation"
import { ShippingNotification } from "./emails/shipping-notification"
import { PasswordReset } from "./emails/password-reset"

const resend = new Resend(process.env.RESEND_API_KEY!)

export async function sendOrderConfirmation(
  to: string,
  props: React.ComponentProps<typeof OrderConfirmation>
) {
  const html = await render(<OrderConfirmation {...props} />)
  const text = await render(<OrderConfirmation {...props} />, { plainText: true })

  return resend.emails.send({
    from: "[email protected]",
    to,
    subject: `Order #${props.orderId.slice(-8)} Confirmed`,
    html,
    text,
  })
}

export async function sendShippingNotification(
  to: string,
  props: React.ComponentProps<typeof ShippingNotification>
) {
  const html = await render(<ShippingNotification {...props} />)

  return resend.emails.send({
    from: "[email protected]",
    to,
    subject: `Your order has shipped!`,
    html,
  })
}

package.json Email Preview

{
  "scripts": {
    "email:dev": "react-email dev --dir emails --port 3001",
    "email:export": "react-email export --outDir ./email-previews"
  },
  "devDependencies": {
    "react-email": "^3.0.5"
  }
}

For the MJML alternative markup language for HTML emails that compiles to cross-client-compatible HTML without the React component model, see the email template patterns. For the Mailchimp transactional API (Mandrill) or Postmark equivalents when extensive email analytics, A/B testing deliverability infrastructure, or suppression list management are needed beyond basic send, the Resend guide covers provider comparison. The Claude Skills 360 bundle includes React Email skill sets covering component templates, Tailwind styling, and Resend integration. Start with the free tier to try email template generation.

Keep Reading

Backend

Claude Code for Bun: Fast JavaScript Runtime and Toolkit

Build with Bun and Claude Code — Bun.serve for HTTP servers, Bun.file for fast file I/O, Bun.$ for shell commands, Bun.sql for SQLite and PostgreSQL, Bun.build for bundling, bun:test for testing, Bun.hash for hashing, bun.lock for deterministic installs, bun run for package.json scripts, hot reloading with --hot, bun init for project scaffolding, and compatibility with Node.js modules.

6 min read Jun 13, 2027
Backend

Claude Code for Express.js Advanced: Patterns for Production APIs

Advanced Express.js patterns with Claude Code — typed request handlers with RequestHandler generics, async error handling middleware, Zod validation middleware factory, rate limiting with express-rate-limit and Redis store, helmet security middleware, compression, dependency injection with tsyringe, file upload with multer and S3, pagination utilities, JWT middleware, and structured logging with pino.

6 min read Jun 8, 2027
Backend

Claude Code for KeystoneJS: Node.js CMS and App Framework

Build full-stack apps with KeystoneJS and Claude Code — config with lists, fields.text and fields.relationship for schema definition, access control with isAuthenticated and isAdmin functions, hooks with beforeOperation and afterOperation, GraphQL API auto-generation from schema, AdminUI for content management, session with statelessSessions, Prisma adapter for database, file storage with images and files fields, and custom REST endpoints.

6 min read Jun 7, 2027

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free