Resend
Send transactional email (auth, billing, invitations) through Resend — wired to the notifications module's mailer port. Drop-in replacement for SMTP / SendGrid / Postmark.
Status: scaffold. Fill in the sections below before publishing.
What you get
The modules/notifications bounded context owns transactional email. The
IMailer port is consumed by iam (verification, password reset, magic-link),
tenancy (member invitations), and billing (receipts). UseDeploy ships
adapters for SMTP, SendGrid, Postmark, and Resend — switched
via MAIL_PROVIDER.
Templates are React Email components rendered at request time, so you get type-checked subject + body + plain-text fallback in one file.
Setup
1. Create the Resend account
In the Resend dashboard:
- Verify the sending domain (DNS records: SPF + DKIM).
- Create an API key with
emails:sendscope.
2. Set env vars
# apps/server/.env
MAIL_PROVIDER=resend
RESEND_API_KEY=re_...
MAIL_FROM="UseDeploy <[email protected]>"
MAIL_REPLY_TO="[email protected]" # optionalWith MAIL_PROVIDER unset, the mailer is a no-op (logs the email payload
to Pino at info level) — perfect for local dev without burning Resend credits.
3. Test the templates
Each template ships with a Storybook-style preview at /admin/mail/preview
(non-production only). Use it to verify rendering before triggering real sends.
The preview accepts ?template=auth.verify-email&locale=es query params.
4. Smoke test
Trigger a password-reset flow from /login → forgot password and confirm the
email lands in the inbox. Cross-check the Resend dashboard → Logs pane for
the message ID.
Where it lives in the codebase
apps/server/src/modules/notifications/application/ports/mailer.ts— the portapps/server/src/modules/notifications/infrastructure/resend/— the adapterapps/server/src/modules/notifications/infrastructure/templates/— React Email components (auth verify, password reset, magic link, invitation, billing receipt)