Features
Email functionality with Supabase Auth and optional Resend integration.
Overview
Email in this template is handled in two ways:
- Supabase Auth emails - Verification and magic links (built-in)
- Transactional emails - Custom emails via Resend (optional)
Supabase Auth Emails
Supabase Auth automatically sends emails for:
- Email verification on signup
- Magic link sign-in
Customizing Auth Email Templates
- Go to Supabase Dashboard → Authentication → Email Templates
- Customize the templates for each email type
- Use variables like
{{ .ConfirmationURL }}for dynamic content
SMTP Configuration
For production, configure custom SMTP in Supabase:
- Go to Project Settings → Auth → SMTP Settings
- Enter your SMTP provider details (Resend, SendGrid, etc.)
- This allows emails to come from your domain
Adding Transactional Emails (Optional)
For custom emails (welcome, purchase confirmation), add Resend.
Install Resend
bun add resendCreate Email Service
Create a server-only email service:
import "server-only";
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function sendWelcomeEmail(to: string, name: string) {
await resend.emails.send({
from: 'noreply@yourdomain.com',
to,
subject: 'Welcome!',
html: `<h1>Welcome, ${name}!</h1><p>Thanks for signing up.</p>`,
});
}
export async function sendPurchaseConfirmation(to: string, amount: number) {
await resend.emails.send({
from: 'noreply@yourdomain.com',
to,
subject: 'Purchase Confirmed',
html: `<p>Thank you for your purchase of $${amount}!</p>`,
});
}Verify Domain
Add DNS records in Resend dashboard for your sending domain.
Email Templates
For complex templates, use React Email:
bun add @react-email/componentsCreate email components:
import { Html, Head, Body, Container, Heading, Text, Link } from '@react-email/components';
export function WelcomeEmail({ name }: { name: string }) {
return (
<Html>
<Head />
<Body>
<Container>
<Heading>Welcome, {name}!</Heading>
<Text>We're excited to have you on board.</Text>
<Link href="https://yourdomain.com/dashboard">Get Started</Link>
</Container>
</Body>
</Html>
);
}Render and send:
import { render } from '@react-email/render';
import { WelcomeEmail } from './templates/welcome';
const html = render(<WelcomeEmail name={name} />);
await resend.emails.send({
from: 'noreply@yourdomain.com',
to,
subject: 'Welcome!',
html,
});Sending on Events
After Signup
Call from the auth service or a database trigger:
export async function signUp({ email, password }: SignUpParams) {
const supabase = await createSupabaseServerClient();
const { data, error } = await supabase.auth.signUp({ email, password });
if (data.user) {
await sendWelcomeEmail(email, email.split('@')[0]);
}
return { ok: true, redirectPath: '/' };
}After Purchase
Integrate with the webhook handler:
case 'checkout.session.completed':
const session = event.data.object as Stripe.Checkout.Session;
if (session.customer_email) {
await sendPurchaseConfirmation(
session.customer_email,
(session.amount_total ?? 0) / 100
);
}
break;Testing
Resend free tier: 100 emails/day, 3,000/month. Sufficient for development.
For local testing without sending real emails:
export async function sendWelcomeEmail(to: string, name: string) {
if (process.env.NODE_ENV === 'development') {
console.log(`[EMAIL] Welcome email to ${to}: Hello ${name}`);
return;
}
await resend.emails.send({ /* ... */ });
}Related
- Authentication - Email verification
- Payments - Purchase confirmations
Was this page helpful?