| name | email-template-builder |
| description | Construtor de templates de e-mail transacional. Cria sistemas completos de e-mail com React Email, integração com provedores, servidor de preview, suporte a i18n, modo escuro, otimização anti-spam e rastreamento de analytics. Produz código pronto para produção para Resend, Postmark, SendGrid ou AWS SES. |
| agents | ["claude-code"] |
Email Template Builder
Tier: POWERFUL
Categoria: Engineering Team
Domínio: E-mail Transacional / Infraestrutura de Comunicações
Visão Geral
Construa sistemas completos de e-mail transacional: templates React Email, integração com provedores, servidor de preview, suporte a i18n, modo escuro, otimização de spam e rastreamento de analytics. Produz código pronto para produção para Resend, Postmark, SendGrid ou AWS SES.
Capacidades Principais
- Templates React Email (boas-vindas, verificação, redefinição de senha, fatura, notificação, digest)
- Templates MJML para máxima compatibilidade com clientes de e-mail
- Suporte a múltiplos provedores com interface de envio unificada
- Servidor de preview local com hot reload
- i18n/localização com chaves de tradução tipadas
- Suporte a modo escuro usando media queries
- Lista de verificação de otimização de pontuação de spam
- Rastreamento de abertura/clique com parâmetros UTM
Quando Usar
- Configurando e-mail transacional para um novo produto
- Migrando de um sistema de e-mail legado
- Adicionando novos tipos de e-mail (fatura, digest, notificação)
- Depurando problemas de entregabilidade de e-mail
- Implementando i18n para templates de e-mail
Estrutura do Projeto
emails/
├── components/
│ ├── layout/
│ │ ├── email-layout.tsx # Layout base com header/footer da marca
│ │ └── email-button.tsx # Componente de botão CTA
│ ├── partials/
│ │ ├── header.tsx
│ │ └── footer.tsx
├── templates/
│ ├── welcome.tsx
│ ├── verify-email.tsx
│ ├── password-reset.tsx
│ ├── invoice.tsx
│ ├── notification.tsx
│ └── weekly-digest.tsx
├── lib/
│ ├── send.ts # Função de envio unificada
│ ├── providers/
│ │ ├── resend.ts
│ │ ├── postmark.ts
│ │ └── ses.ts
│ └── tracking.ts # UTM + analytics
├── i18n/
│ ├── en.ts
│ └── de.ts
└── preview/ # Servidor de preview para desenvolvimento
└── server.ts
Layout Base de E-mail
import {
Body, Container, Head, Html, Img, Preview, Section, Text, Hr, Font
} from "@react-email/components"
interface EmailLayoutProps {
preview: string
children: React.ReactNode
}
export function EmailLayout({ preview, children }: EmailLayoutProps) {
return (
<Html lang="en">
<Head>
<Font
fontFamily="Inter"
fallbackFontFamily="Arial"
webFont={{ url: "https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfAZ9hiJ-Ek-_EeA.woff2", format: "woff2" }}
fontWeight={400}
fontStyle=
/>
{/* Estilos para modo escuro */}
{preview}
{/* Header */}
{/* Conteúdo */}
{children}
{/* Footer */}
MyApp Inc. · 123 Main St · San Francisco, CA 94105
Unsubscribe
{" · "}
Privacy Policy
)
}
styles = {
: { : , : },
: { : , : , : , : , : },
: { : , : },
: { : },
: { : , : },
: { : },
: { : , : , : , : },
: { : , : },
}
E-mail de Boas-Vindas
import { Button, Heading, Text } from "@react-email/components"
import { EmailLayout } from "../components/layout/email-layout"
interface WelcomeEmailProps {
name: "string"
confirmUrl: string
trialDays?: number
}
export function WelcomeEmail({ name, confirmUrl, trialDays = 14 }: WelcomeEmailProps) {
return (
<EmailLayout preview={`Welcome to MyApp, ${name}! Confirm your email to get started.`}>
<Heading style={styles.h1}>Welcome to MyApp, {name}!</Heading>
<Text style={styles.text}>
We're excited to have you on board. You've got {trialDays} days to explore everything MyApp has to offer — no credit card required.
</Text>
< =>
First, confirm your email address to activate your account:
Confirm Email Address
Button not working? Copy and paste this link into your browser:
{confirmUrl}
Once confirmed, you can:
Connect your first project in 2 minutes
Invite your team (free for up to 3 members)
Set up Slack notifications
)
}
styles = {
: { : , : , : , : },
: { : , : , : , : },
: { : , : , : , : , : , : , : , : , : },
: { : , : },
: { : },
: { : , : , : , : },
}
E-mail de Fatura
import { Row, Column, Section, Heading, Text, Hr, Button } from "@react-email/components"
import { EmailLayout } from "../components/layout/email-layout"
interface InvoiceItem { description: string; amount: number }
interface InvoiceEmailProps {
name: "string"
invoiceNumber: string
invoiceDate: string
dueDate: string
items: InvoiceItem[]
total: number
currency: string
downloadUrl: string
}
export function InvoiceEmail({ name, invoiceNumber, invoiceDate, dueDate, items, total, currency = "USD", downloadUrl }: InvoiceEmailProps) {
const formatter = new Intl.NumberFormat("en-US", { style: "currency", currency })
(
)
}
styles = {
: { : , : , : , : },
: { : , : , : , : },
: { : , : , : , : },
: { : , : , : , : , : },
: { : , : , : },
: { : , : , : , : },
: { : , : },
: { : , : },
: { : , : , : , : , : },
: { : },
: { : },
: { : , : , : },
: { : , : },
: { : , : , : , : },
: { : , : , : , : , : },
: { : , : , : , : , : , : , : },
}
Função de Envio Unificada
import { Resend } from "resend"
import { render } from "@react-email/render"
import { WelcomeEmail } from "../templates/welcome"
import { InvoiceEmail } from "../templates/invoice"
import { addTrackingParams } from "./tracking"
const resend = new Resend(process.env.RESEND_API_KEY)
type EmailPayload =
| { type: "welcome"; props: Parameters<typeof WelcomeEmail>[0] }
| { type: "invoice"; props: Parameters<typeof InvoiceEmail>[0] }
export async function sendEmail(to: string, payload: EmailPayload) {
const templates = {
welcome: { component: WelcomeEmail, : },
: { : , : },
}
template = templates[payload.]
html = (template.(payload. ))
trackedHtml = (html, { : payload. })
result = resend..({
: ,
to,
: template.,
: trackedHtml,
: [{ : , : payload. }],
})
result
}
Configuração do Servidor de Preview
{
"scripts": {
"email:dev": "email dev --dir emails/templates --port 3001",
"email:build": "email export --dir emails/templates --outDir emails/out"
}
}
Suporte a i18n
export const en = {
welcome: {
preview: (name: "string-welcome-to-myapp-name"
heading: (name: "string-welcome-to-myapp-name"
body: (days: number) => `You've got ${days} days to explore everything.`,
cta: "Confirm Email Address",
},
}
export const de = {
welcome: {
preview: (name: "string-willkommen-bei-myapp-name"
heading: (name: "string-willkommen-bei-myapp-name"
body: (days: number) => `Du hast ${days} Tage Zeit, alles zu erkunden.`,
cta: "E-Mail-Adresse bestätigen",
},
}
import { en, de } from "../i18n"
const t = locale === "de" ? de : en
Lista de Verificação de Otimização de Pontuação de Spam
Rastreamento de Analytics
interface TrackingParams {
campaign: string
medium?: string
source?: string
}
export function addTrackingParams(html: string, params: TrackingParams): string {
const utmString = new URLSearchParams({
utm_source: params.source ?? "email",
utm_medium: params.medium ?? "transactional",
utm_campaign: params.campaign,
}).toString()
return html.replace(/href="(https?:\/\/[^"]+)"/g, (match, url) => {
const separator = url.includes("?") ? "&" : "?"
return `href="${url}${separator}${utmString}"`
})
}
Armadilhas Comuns
- Estilos inline são obrigatórios — a maioria dos clientes de e-mail remove os estilos
<head>; o React Email lida com isso
- Largura máxima de 600px — qualquer coisa mais larga quebra no Gmail mobile
- Sem flexbox/grid — use
<Row> e <Column> do react-email, não CSS grid
- Media queries para modo escuro — deve usar
!important para substituir estilos inline
- Texto simples ausente — todos os principais provedores têm um campo de texto simples; sempre preencha
- E-mail transacional vs. marketing — use domínios/IPs de envio separados para proteger a entregabilidade