Trasforma le email in fatturato con Brew.
Per i team con le email nel codice: fanne l’inventario con un agente di coding, portale su un canvas di Brew tramite MCP, poi migrale e migliorale in sicurezza.

Le email nel codice sono email di prodotto definite nel tuo codebase e rilasciate come qualsiasi altra funzionalità. In un team che lavora con Resend e React Email, se chiedi quali email invia il prodotto, segue un attimo di silenzio. L’email di benvenuto è un componente in emails/. La reimpostazione della password sta nella dashboard del provider di autenticazione. L’email di fine prova è una stringa in un cron job. La ricevuta la invia Stripe. Nessuno ricorda cosa invii l’email “Ci manchi”.
Ogni email è stata facile da rilasciare, quindi nessuno ha il quadro completo. Noi risolveremmo il problema in quest’ordine: prima la visibilità, poi la migrazione, poi il miglioramento. Gran parte del lavoro può farla l’agente di coding che usi già, collegato a Brew tramite MCP.
import_email. L’importazione è deterministica, non usa l’IA ed è gratuita.React Email e Resend hanno migliorato di molto le email per gli sviluppatori: componenti tipizzati, revisionati nelle pull request. Il conto arriva dopo.
Le email sono sparse. Componenti, HTML inline in un job in background, modelli nella dashboard di un servizio esterno, email che un altro servizio invia per te. Nessun file le elenca tutte.
Le anteprime non sono la produzione. Il server di anteprima di React Email mostra un modello con le sue props di anteprima, non quello che ha ricevuto un cliente, e niente degli altri modelli.
Solo gli sviluppatori possono vederle. Prodotto, design e supporto dovrebbero chiedere a uno sviluppatore di avviare il progetto, quindi quasi sempre rinunciano.
Dopo il lancio nessuno le rivede. L’email di due anni fa ha ancora il vecchio logo e un piano che non vendi più. Nessuno se ne accorge, perché nessuno le vede tutte insieme.
L’obiettivo è una vista condivisa di tutte le email. Niente di quello che segue tocca la produzione.

Ogni fase è utile anche da sola, e puoi fermarti dopo una qualsiasi.
Il server MCP di Brew si trova all’indirizzo https://brew.new/api/mcp e usa OAuth: accedi con Brew e scegli il brand in cui l’agente può lavorare. In Claude Code:
claude mcp add --transport http brew "https://brew.new/api/mcp"Il comando salva il server solo nella configurazione locale di questo progetto. Per usarlo in tutti i progetti, aggiungi --scope user. Prima di usarne gli strumenti, esegui claude mcp login brew oppure apri /mcp e autentica il collegamento a Brew.
La documentazione sulla configurazione dei client ha sezioni dedicate a Cursor e Codex. I client senza OAuth possono usare una chiave API limitata al brand. Poi fai richiamare all’agente get_brew_capabilities, così legge l’elenco aggiornato degli strumenti invece di tirare a indovinare.
Chiedi all’agente un elenco:
Find every email this codebase sends. Search for provider calls
(resend.emails.send, postmark, sendgrid, nodemailer, SES), React Email
components and render() calls, and any email templates referenced from
config or a third-party dashboard.
For each email, record: a name, what triggers it, the file and line that
sends it, the template file, the provider, and the variables it uses.
Write the result as a table in EMAILS.md. List anything you could not
resolve under "Unknown" instead of guessing.Tieni la sezione “Unknown”, quella delle email non identificate. Le conferme di autenticazione e le ricevute di Stripe non sono chiamate di invio nel tuo codice, ma devono stare nell’elenco. Fai il commit di EMAILS.md. Anche se ti fermi qui, hai un elenco che ieri non avevi.
Il miglior input per l’importazione è l’HTML che il tuo codice produce già. L’utility render di React Email ti restituisce quella stringa:
import { render } from 'react-email'
import WelcomeEmail from './emails/welcome'
const html = await render(
<WelcomeEmail firstName="Ana" planName="Pro" trialDays={14} />
)I progetti meno recenti importano render da @react-email/render. Usa dati di esempio realistici, non "test", perché il tuo team rivedrà queste email. Fai scrivere all’agente uno script che renderizzi ogni modello in un file.
Brew importa anche direttamente un modulo React Email con format: "jsx", leggendolo in modo statico senza eseguirlo. Le props prendono i valori predefiniti o quelli di PreviewProps, i componenti importati da altri file locali vengono scartati o rifiutati, e await e costrutti simili non sono accettati. Se il modello non sta in un unico file autosufficiente, usa l’HTML renderizzato.
Poi importa ogni render con import_email, con un groupName per ogni area del prodotto:
For each rendered email in ./email-renders, call import_email with
format "html", the title and subject line from EMAILS.md, and a
groupName by area: "Auth", "Onboarding", "Billing" or "Lifecycle".
Report the emailId for each one and any warnings in its assetReport.Gli sviluppatori si chiedono, giustamente, se l’importazione riscrive le loro email. Non lo fa:
assetReport elenca quelle che non è riuscito a recuperare.baseUrl serve solo a risolvere i percorsi relativi delle immagini.Ogni gruppo ha il suo canvas. Apri brew.new/emails/onboarding e trovi l’intera sequenza fianco a fianco, con un selettore desktop/mobile e i commenti su ogni design. I link al canvas funzionano per chi ha effettuato l’accesso al tuo workspace di Brew. Non esiste un link di condivisione pubblico, quindi invita i tuoi revisori.
È qui che emergono i problemi: due loghi, un pulsante con un link rotto, tre footer. Esegui audit_email prima di correggere qualsiasi cosa. Controlla link, immagini, conformità, dimensione caricata, supporto dei client, accessibilità e testi, costa 5 crediti per ogni audit completo e accetta un emailId salvato o HTML grezzo, quindi puoi fare l’audit anche delle email che non hai importato. La nostra checklist di controllo qualità prima dell’invio spiega ogni controllo e ogni soglia.
Ora hai un inventario, tutte le email su un canvas e un elenco di problemi, e il tuo codice invia ancora tutto come prima.
Ora alcune email le invia Brew al posto del tuo codice. Non tutte le email devono essere spostate, e un determinato tipo di email lo invia sempre un solo sistema alla volta.
| Oggi nel tuo codice | In Brew |
|---|---|
resend.emails.send({ react: <WelcomeEmail /> }) |
Un evento trigger più un’automazione pubblicata con un passaggio Invia email |
| Props passate al componente | Campi del payload del trigger, usati come merge tag, per esempio {{ firstName | there }} o {{ trigger.planName }} |
Il dominio from |
Un dominio di invio verificato in Brew |
| La tua tabella degli utenti | Contatti, creati tramite l’API REST o un’integrazione |
| Un cron job che invia una sequenza | Un’automazione con passaggi Attesa, Filtro e Invia email |
L’agente richiama create_domain per ottenere i record DNS, poi verify_domain quando sono attivi. I domini creati tramite MCP e API sono domini di marketing. Per le reimpostazioni della password e le ricevute, configura nell’app di Brew un dominio con finalità transazionale: non aggiunge il footer di disiscrizione e consegna anche ai contatti disiscritti. La pagina Verificare il dominio di invio della documentazione spiega i record.
MCP aggiorna i contatti ma non li crea. Creali dal tuo backend con POST /v1/contacts, che crea o aggiorna un singolo contatto o un lotto fino a 1.000 contatti e crea automaticamente i campi personalizzati, oppure carica un CSV nell’app. Anche l’attivazione di un trigger crea o aggiorna il contatto presente nel suo payload. Importa solo le persone che hanno accettato di ricevere tue comunicazioni. La pagina Aggiungere contatti della documentazione spiega cosa si aspetta Brew.
È facile non accorgersene: l’email di benvenuto importata dice letteralmente “Hi Ana”. Sostituisci ogni valore di esempio con un merge tag come {{ firstName | there }}, dove il testo dopo la barra verticale è il valore di riserva. Usa l’editor di Brew, oppure fai eseguire all’agente edit_email limitando la modifica a quelle sostituzioni. È una modifica con l’IA che consuma crediti, quindi controlla l’anteprima. La pagina Merge tag della documentazione riporta la sintassi.
L’agente crea un trigger con save_trigger. Lo schema del payload deve includere l’email del destinatario. Assegnagli un contratto tipizzato (infer_payload_contract ne prepara una bozza a partire da un payload di esempio, set_trigger_contract lo salva), poi recuperalo con get_trigger_contract in formato ts o zod, così il tuo backend e Brew concordano sulla struttura del payload.
Poi save_automation crea il trigger più un passaggio Invia email con l’email, il dominio e l’oggetto. L’automazione resta in bozza finché non la pubblichi. dryRun convalida il diagramma, test_automation invia una copia reale al tuo indirizzo e check_trigger conferma che un’automazione pubblicata è in ascolto prima che la produzione attivi qualcosa.
È l’unica modifica al codice della tua applicazione. Prima, con Resend:
await resend.emails.send({
from: 'Acme <hello@acme.com>',
to: user.email,
subject: 'Welcome to Acme',
react: <WelcomeEmail firstName={user.firstName} planName={plan.name} />,
})Dopo, con Brew:
const res = await fetch(
`https://brew.new/api/v1/automations/triggers/${process.env.BREW_WELCOME_TRIGGER_ID}/fire`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BREW_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `welcome-${user.id}`,
},
body: JSON.stringify({
payload: { email: user.email, firstName: user.firstName, planName: plan.name },
}),
}
)
if (!res.ok) {
// 422 means the automation is still a draft; 400 means the payload failed the schema.
throw new Error(`Brew trigger failed: ${res.status} ${await res.text()}`)
}fetch si risolve anche quando la richiesta viene rifiutata, quindi controlla res.ok e lascia che il tuo job runner riprovi o invii un avviso. L’endpoint restituisce 202 quando accetta l’evento e 422 se nessuna automazione pubblicata è in ascolto sul trigger.
Costruisci la Idempotency-Key a partire da un ID stabile, come quello dell’utente o dell’ordine. Una chiave ripetuta restituisce l’esecuzione originale invece di inviare due volte, e riutilizzare una chiave con un corpo diverso restituisce 409 IDEMPOTENCY_CONFLICT. Brew conserva la chiave di un’attivazione finché conserva la ricevuta del trigger, cioè 90 giorni, non le 24 ore usate da molte API. Considera le chiavi permanenti, una per azione. Una chiave basata su un timestamp cambia a ogni nuovo tentativo, e una chiave riutilizzata settimane dopo per un’azione diversa può essere trattata come una ripetizione, senza che l’email parta.
Il codice di produzione chiama questo endpoint con una chiave API, non tramite MCP. Sui collegamenti OAuth, MCP chiede a una persona di confermare invii reali, attivazioni dei trigger e pubblicazioni: giusto in una chat, sbagliato in un gestore di richieste. La guida MCP o REST spiega come dividere il lavoro.
EMAILS.md.La guida alla migrazione da Loops segue lo stesso schema.
Le email di conferma e i magic link di Supabase continuano a partire da Supabase. L’integrazione di Brew con Supabase ascolta gli eventi degli utenti per avviare le automazioni, non sostituisce le email di Supabase Auth. Anche una fattura dettagliata, costruita al momento dell’invio a partire da dati complessi, può essere più semplice da gestire nel codice, quindi verifica prima di cosa hanno bisogno i tuoi merge tag. Tieni sul canvas le copie importate, così anche queste email restano visibili.
Fai l’audit dell’intero insieme. Esegui audit_email su un gruppo, correggi e ripeti prima degli invii più grandi.
Controlla i client reali. test_email_rendering restituisce screenshot da client di posta e dispositivi specifici, modalità scura compresa, per 10 crediti a esecuzione. create_inbox_placement_test invia una copia reale a delle inbox di test e riporta dove è arrivata, sempre per 10 crediti.
Rendi coerente l’insieme. Correggi le incoerenze nell’editor, oppure fai applicare all’agente una modifica, come un nuovo footer, a tutto un gruppo con edit_email.
Leggi i risultati. get_email_analytics riporta invii ed engagement. list_insights restituisce gli insight che Brew ha rilevato nel tuo account, ciascuno con le metriche su cui si basa.
Testa le varianti in modo mirato. Crea le varianti sul canvas e smista i contatti con un passaggio Divisione basato sul comportamento, per esempio se hanno cliccato. Brew non sceglie per te la variante vincente di una divisione casuale, quindi confronta tu le varianti.
Mantieni visibili le nuove email. Aggiungi una riga ad AGENTS.md o a un file simile: le nuove email di prodotto si creano in Brew, partono tramite trigger e si aggiungono a EMAILS.md nella stessa pull request.
Sì. import_email accetta HTML renderizzato, MJML, un messaggio .eml salvato o un modulo React Email. L’HTML renderizzato è l’opzione più affidabile, perché un modulo viene letto in modo statico: le props assumono i valori predefiniti o di anteprima, e i componenti importati da altri file locali vengono esclusi.
No. Non esiste un’integrazione con Resend, né un’importazione o un’esportazione. Importi l’HTML che il tuo codice renderizza e, se fai la migrazione, il tuo codice attiva un trigger di Brew invece di chiamare Resend.
No. Usa MCP da un agente di coding per configurazione, importazioni, audit e test. Il codice di produzione dovrebbe chiamare l’API REST con una chiave API, perché sui collegamenti OAuth MCP chiede a una persona di confermare gli invii reali e le attivazioni dei trigger.
L’importazione converte l’email in un design di Brew modificabile e mantiene l’HTML sorgente originale per l’invio. Rimuove script, iframe, moduli e gestori di eventi, neutralizza i pixel di tracciamento già presenti e copia le immagini pubbliche sull’hosting di Brew. Rivedi ogni email sul canvas, nelle viste desktop e mobile, prima di inviarla da Brew.
