Which emails the app sends, the three mailers (SMTP, Resend, log only), and how email works locally.
Two systems send email:
- Supabase Auth sends sign-in emails: confirmation, password reset, email change, magic link. Configure them in Supabase. See Email sign-in.
- The app sends everything else through
@repo/mailers(packages/mailers).
What the app sends
| Sent from | Template | |
|---|---|---|
| Team invitation | account-invitations-dispatcher.service.ts | invite.email.tsx |
| One-time code for a sensitive action (delete an account or team, transfer ownership) | packages/otp | otp.email.tsx |
| Confirmation after a personal account is deleted | delete-personal-account.service.ts | account-delete.email.tsx |
| Contact form message, to you | (marketing)/contact | Inline HTML in the server action |
| Showcase submission, to you | (marketing)/showcase | Inline HTML in the server action |
The templates are React Email components in packages/email-templates/src/emails/, with their text in packages/email-templates/src/locales/en/. The developer tool (http://localhost:3010, started by pnpm dev) has an emails page for previewing them.
Pick a mailer
MAILER_PROVIDER chooses how the app's emails go out:
| Value | Sends with | Needs |
|---|---|---|
nodemailer (default) | Any SMTP server | EMAIL_HOST, EMAIL_PORT, EMAIL_USER, EMAIL_PASSWORD, EMAIL_TLS (TLS stays on unless set to false). Node.js runtime only |
resend | Resend's HTTP API | RESEND_API_KEY |
log | Nothing. Logs the recipient's domain and the subject | Nothing |
Every email the app sends uses EMAIL_SENDER as the from address, for example "Your product <hello@yourdomain.com>". The contact form and showcase form need CONTACT_EMAIL, the address that receives them.
log is for places where email must not reach real inboxes, such as the live demo. It logs only the domain, not the full address, so logs do not collect what visitors typed.
Locally
apps/web/.env.development sets MAILER_PROVIDER=nodemailer and points it at the local Supabase stack's mail server on port 54325. Supabase Auth's local emails go to the same inbox. Open Mailpit at http://localhost:54324 to read everything that was sent.
Add another provider
Add the name to packages/mailers/core/src/provider-enum.ts and register a factory for it in packages/mailers/core/src/registry.ts that returns an object with sendEmail(). The log mailer in that file is a short example.