rekkal sends transactional email with Resend and authors templates with React Email.
Environment variables
Email reads two variables (listed in.env.example):
RESEND_API_KEY— the Resend API key. Server-only; never import it into a"use client"module.RESEND_FROM— thefromaddress (e.g."Acme <hello@acme.com>"). Must be on a verified domain in production; falls back to Resend’s sandbox sender when unset.
The client — lib/resend.ts
lib/resend.ts exports getResend(), a lazily-constructed client (mirroring getStripe()). Construction is deferred because the Resend SDK throws when the key is absent — so the app still builds and runs without email configured, and callers gate sends on the key being present.
Sending — lib/email.ts
Don’t call getResend() directly from feature code — use the helpers in lib/email.ts: sendWelcomeEmail(...) and sendSubscriptionActiveEmail(...). Each one:
- No-ops when email is not configured (
RESEND_API_KEYabsent or theemailfeature flag off), so local dev and CI never error. - Is best-effort and non-throwing — the Resend SDK returns
{ data, error }(it does not throw); errors are logged, never propagated, so a mail failure can’t break signup or a webhook. - Passes an idempotency key (
welcome-email/<userId>,subscription-active/<subscriptionId>) so a retry never sends twice.
sendWelcomeEmail is driven by sendWelcomeIfNeeded in lib/welcome.ts, which sends at most once per user by checking profiles.welcomed_at. It runs from /auth/callback after the code exchange, and from the sign-up action only when Supabase returns a session outright (email confirmation disabled) — never on the unconfirmed path, which is unauthenticated and would let anyone mail an address they don’t control. sendSubscriptionActiveEmail is sent from the Stripe webhook on a successful checkout.
Templates — emails/
Email templates are React components under emails/, authored with React Email primitives, and passed to Resend via the SDK’s react option (which renders both HTML and plain text). The starter ships emails/welcome-email.tsx and emails/subscription-active-email.tsx. Add new templates as sibling files and send them from a helper in lib/email.ts.
Further reading
Theresend skill is pre-bundled (see agent-skills.md) and carries gotchas — idempotency keys, webhook verification, template variable syntax — worth reading before sending in production.