This page covers both email contact sync (building your mailing list) and auth emails (magic links, password resets). One provider handles both jobs.
What Email Does in This Repo
The email service handles two things through a single provider:- Contact sync — when a user signs in, they’re created as a contact in your email tool
- Auth emails — magic link and password reset emails are delivered through the same provider
If contact sync fails, sign-in still works normally. Auth email delivery is stricter because the user needs that email to finish the flow.
Pick Your Provider
- Loops
- Resend
- Brevo
Best for: Simple defaults, easy contact syncing, and templated auth emails.Loops uses transactional template IDs for auth emails, so you’ll create the email templates in Loops and reference them by ID.
Provider Selection
Set the provider with:loops, resend, brevo, none
Setup
Set up templates (Loops only)
If you’re using Loops, create transactional email templates for magic links and password resets, then add their IDs to your env vars.
Key Files
lib/email/contacts.ts— contact sync logiclib/email/providers/*— provider-specific implementationslib/email/auth-emails.ts— auth email delivery
Verify It Works
Your email setup is correct if:
- A test user signs in successfully
- Auth emails arrive for magic link and forgot password
- The user appears in your chosen email provider
- The app still works even if contact sync temporarily fails
Common Mistakes
Wrong provider name in env vars
Wrong provider name in env vars
Make sure
NEXT_PUBLIC_EMAIL_PROVIDER is exactly loops, resend, or brevo. Typos will silently disable email.Missing AUTH_EMAIL_FROM
Missing AUTH_EMAIL_FROM
Auth emails need a sender address. Without
AUTH_EMAIL_FROM, delivery will fail.Using Loops without template IDs
Using Loops without template IDs
Loops requires
LOOPS_AUTH_MAGIC_LINK_TRANSACTIONAL_ID and LOOPS_AUTH_RESET_PASSWORD_TRANSACTIONAL_ID. Without them, auth emails won’t send.Segment/list/attribute ID doesn't exist
Segment/list/attribute ID doesn't exist
If you reference a segment, list, or attribute that doesn’t exist in your provider, contact sync will fail silently.
Expecting auth emails with provider set to 'none'
Expecting auth emails with provider set to 'none'
EMAIL_PROVIDER=none disables everything. No contact sync, no auth emails.
