Recipe: Add a transactional email
Recipe: Add a transactional email
-
Create the template in
emails/your-email.tsx:import { Text } from "@react-email/components"; import { EmailButton, EmailLayout } from "./components/layout"; export function YourEmail({ someProp }: { someProp: string }) { return ( <EmailLayout preview="Short inbox preview text" heading="Your heading"> <Text style={{ fontSize: "14px", color: "#3f3f46", lineHeight: "22px" }}> Body copy. {someProp} </Text> <EmailButton href="https://example.com">Call to action</EmailButton> </EmailLayout> ); } export default YourEmail; // Shown by `npm run email:dev`'s preview server. YourEmail.PreviewProps = { someProp: "example value" };Use
EmailLayout/EmailButtonfromemails/components/layout.tsxfor consistent branding — plain inline styles only, email clients don't run Tailwind. -
Preview it:
npm run email:dev, open the printed URL, find your file in the sidebar. Edits hot-reload. -
Send it from server code:
import { sendEmail } from "@/lib/email"; import { YourEmail } from "@/emails/your-email"; await sendEmail({ to: user.email, subject: "Your subject line", react: YourEmail({ someProp: "value" }), // critical: true only if the user is blocked without this email // (verification, password reset) — otherwise leave it best-effort. }); -
Verify: without
RESEND_API_KEYset, confirm you see[email] RESEND_API_KEY not set — skipping "Your subject line" to ...in the server log rather than an error. With a real key, check the Resend dashboard for delivery.
To remove an email, delete its file from emails/ and the sendEmail
call site — there's no registry to update elsewhere.