Email

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

EmailSent fromTemplate
Team invitationaccount-invitations-dispatcher.service.tsinvite.email.tsx
One-time code for a sensitive action (delete an account or team, transfer ownership)packages/otpotp.email.tsx
Confirmation after a personal account is deleteddelete-personal-account.service.tsaccount-delete.email.tsx
Contact form message, to you(marketing)/contactInline HTML in the server action
Showcase submission, to you(marketing)/showcaseInline 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:

ValueSends withNeeds
nodemailer (default)Any SMTP serverEMAIL_HOST, EMAIL_PORT, EMAIL_USER, EMAIL_PASSWORD, EMAIL_TLS (TLS stays on unless set to false). Node.js runtime only
resendResend's HTTP APIRESEND_API_KEY
logNothing. Logs the recipient's domain and the subjectNothing

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.