ignitionstack.pro v1.0 is out! Read the announcement →
Skip to Content

Email & Notifications

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.

Arquitetura de Emails

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 configurado

Environment Variables

Criar conta no Resend

Acesse resend.com  e crie uma conta gratuita.

Obter API Key

No Dashboard → API Keys → Create API Key:

.env.local
# 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.com

Verify a domain (production)

To send from your own domain:

  1. Dashboard → Domains → Add Domain
  2. Adicione os registros DNS (MX, TXT, DKIM)
  3. Wait for verification (up to 48h)

Without a verified domain, emails are sent from onboarding@resend.dev (testing only).

Client configuration

src/lib/resend.ts
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, }

Contact form

Server Action

src/app/actions/email/send-contact.ts
'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' } } }

Template React Email

src/app/emails/contact-template.tsx
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', }

Email de Boas-Vindas

Send automatically after signup via Supabase webhook or trigger:

src/app/actions/email/send-welcome.ts
'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 } } }

Form component

src/app/components/contact-form.tsx
'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> ) }

Preview de Templates

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/emails

Acesse http://localhost:3001 para ver os templates.

Webhooks com Resend

Resend pode notificar sobre entregas, bounces e cliques:

src/app/api/webhooks/resend/route.ts
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.

Troubleshooting

Email never arrives

Erro “Domain not verified”

Template does not render

Rate Limits

PlanEmails/monthEmails/second
Free3.0001
Pro50.00010
EnterpriseIlimitadoCustom

Recursos