All outbound communication (contact form, future automations, webhooks) uses Resend . This page explains how to configure the service and how the boilerplate reacts to events.
Resend offers 3,000 free emails/month, a modern SDK, and native React Email integration for templates.
src/app/
├── api/
│ └── contact/route.ts # Contact form API
├── actions/
│ └── email/
│ ├── send-contact.ts # Enviar email de contato
│ └── send-welcome.ts # Email de boas-vindas
├── emails/ # Templates React Email
│ ├── contact-template.tsx
│ ├── welcome-template.tsx
│ └── components/
│ └── email-layout.tsx
└── lib/
└── resend.ts # Cliente Resend configuradoAcesse resend.com e crie uma conta gratuita.
No Dashboard → API Keys → Create API Key:
# Resend
RESEND_API_KEY=re_...
# Default email to receive contacts
CONTACT_EMAIL=seu-email@dominio.com
# From email (must verify the domain)
FROM_EMAIL=noreply@seu-dominio.comTo send from your own domain:
Without a verified domain, emails are sent from onboarding@resend.dev (testing only).
import { Resend } from 'resend'
export const resend = new Resend(process.env.RESEND_API_KEY)
export const emailConfig = {
from: process.env.FROM_EMAIL || 'onboarding@resend.dev',
replyTo: process.env.CONTACT_EMAIL,
}'use server'
import { resend, emailConfig } from '@/lib/resend'
import ContactTemplate from '@/app/emails/contact-template'
interface ContactFormData {
name: string
email: string
message: string
}
export async function sendContactEmail(data: ContactFormData) {
try {
const { error } = await resend.emails.send({
from: emailConfig.from,
to: process.env.CONTACT_EMAIL!,
replyTo: data.email,
subject: `[Contact] ${data.name}`,
react: ContactTemplate({
name: data.name,
email: data.email,
message: data.message,
}),
})
if (error) {
console.error('Email error:', error)
return { success: false, error: 'Failed to send email' }
}
return { success: true }
} catch (error) {
console.error('Send email error:', error)
return { success: false, error: 'Internal error' }
}
}import {
Body,
Container,
Head,
Heading,
Html,
Preview,
Section,
Text,
} from '@react-email/components'
interface ContactTemplateProps {
name: string
email: string
message: string
}
export default function ContactTemplate({
name,
email,
message,
}: ContactTemplateProps) {
return (
<Html>
<Head />
<Preview>New message from {name}</Preview>
<Body style={main}>
<Container style={container}>
<Heading style={h1}>New Contact Message</Heading>
<Section style={section}>
<Text style={label}>Name:</Text>
<Text style={value}>{name}</Text>
<Text style={label}>Email:</Text>
<Text style={value}>{email}</Text>
<Text style={label}>Message:</Text>
<Text style={value}>{message}</Text>
</Section>
</Container>
</Body>
</Html>
)
}
// Inline styles (required for emails)
const main = {
backgroundColor: '#f6f9fc',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
}
const container = {
backgroundColor: '#ffffff',
margin: '0 auto',
padding: '20px',
maxWidth: '600px',
}
const h1 = {
color: '#1a1a1a',
fontSize: '24px',
fontWeight: '600',
}
const section = {
padding: '20px 0',
}
const label = {
color: '#666',
fontSize: '12px',
textTransform: 'uppercase' as const,
marginBottom: '4px',
}
const value = {
color: '#1a1a1a',
fontSize: '16px',
marginBottom: '16px',
}Send automatically after signup via Supabase webhook or trigger:
'use server'
import { resend, emailConfig } from '@/lib/resend'
import WelcomeTemplate from '@/app/emails/welcome-template'
export async function sendWelcomeEmail(email: string, name: string) {
try {
await resend.emails.send({
from: emailConfig.from,
to: email,
subject: 'Welcome to ignitionstack.pro!',
react: WelcomeTemplate({ name }),
})
return { success: true }
} catch (error) {
console.error('Welcome email error:', error)
return { success: false }
}
}'use client'
import { useState } from 'react'
import { sendContactEmail } from '@/app/actions/email/send-contact'
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle')
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault()
setStatus('loading')
const formData = new FormData(e.currentTarget)
const data = {
name: formData.get('name') as string,
email: formData.get('email') as string,
message: formData.get('message') as string,
}
const result = await sendContactEmail(data)
if (result.success) {
setStatus('success')
e.currentTarget.reset()
} else {
setStatus('error')
}
}
return (
<form onSubmit={handleSubmit} className="space-y-4">
<input
name="name"
placeholder="Name"
required
className="w-full p-3 border rounded"
/>
<input
name="email"
type="email"
placeholder="Email"
required
className="w-full p-3 border rounded"
/>
<textarea
name="message"
placeholder="Message"
required
rows={4}
className="w-full p-3 border rounded"
/>
<button
type="submit"
disabled={status === 'loading'}
className="w-full p-3 bg-primary text-white rounded"
>
{status === 'loading' ? 'Sending...' : 'Send'}
</button>
{status === 'success' && (
<p className="text-green-600">Message sent successfully!</p>
)}
{status === 'error' && (
<p className="text-red-600">Failed to send. Try again.</p>
)}
</form>
)
}Use o pacote react-email para preview local:
# Install if you don't have it yet
npm install react-email @react-email/components
# Rodar preview server
npx email dev --dir src/app/emailsAcesse http://localhost:3001 para ver os templates.
Resend pode notificar sobre entregas, bounces e cliques:
import { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.json()
switch (body.type) {
case 'email.delivered':
console.log('Email entregue:', body.data.email_id)
break
case 'email.bounced':
console.log('Email retornou:', body.data.email_id)
// Mark the email as invalid in the DB
break
case 'email.complained':
console.log('Spam complaint:', body.data.email_id)
// Remover da lista de emails
break
}
return new Response('OK')
}Configure no Dashboard → Webhooks → Add Webhook.
.env.localonboarding@resend.dev para testes@react-email/componentsnpx email dev| Plan | Emails/month | Emails/second |
|---|---|---|
| Free | 3.000 | 1 |
| Pro | 50.000 | 10 |
| Enterprise | Ilimitado | Custom |