Transformez vos e-mails en revenus avec Brew.
Vos e-mails sont dans le code ? Inventoriez-les avec un agent de code, réunissez-les sur un canevas Brew via MCP, puis migrez-les et améliorez-les sans risque.

Les e-mails dans le code, ce sont les e-mails produit définis dans votre base de code et livrés comme n’importe quelle autre fonctionnalité. Dans une équipe qui s’appuie sur Resend et React Email, demandez quels e-mails le produit envoie : un silence s’installe. L’e-mail de bienvenue est un composant dans emails/. La réinitialisation du mot de passe se trouve dans le tableau de bord du fournisseur d’authentification. L’e-mail de fin d’essai est une chaîne de caractères dans un job cron. Stripe envoie le reçu. Et personne ne se souvient de ce qui envoie l’e-mail « Vous nous manquez ».
Chaque e-mail a été facile à livrer, si bien que personne n’a la vue d’ensemble. Nous procéderions dans l’ordre : la visibilité, puis la migration, puis l’amélioration. L’agent de code que vous utilisez déjà peut s’en charger en grande partie, une fois connecté à Brew via MCP.
import_email. L’import est déterministe, n’utilise pas d’IA et est gratuit.React Email et Resend ont nettement amélioré l’e-mail pour les développeurs : des composants typés, relus dans des pull requests. Le prix à payer apparaît plus tard.
Les e-mails sont éparpillés. Des composants, du HTML écrit en dur dans un job en arrière-plan, des modèles dans le tableau de bord d’un tiers, des e-mails qu’un autre service envoie pour vous. Aucun fichier ne les recense tous.
Les aperçus ne reflètent pas la production. Le serveur d’aperçu de React Email affiche un modèle avec ses props d’aperçu, pas ce qu’un client a reçu, et rien des autres modèles.
Seuls les développeurs peuvent les voir. Le produit, le design et le support devraient demander à un développeur de lancer le projet ; la plupart du temps, ils s’en abstiennent.
Rien n’est relu après le lancement. L’e-mail d’il y a deux ans affiche toujours l’ancien logo et une offre que vous ne vendez plus. Personne ne le remarque, car personne ne voit les e-mails tous ensemble.
L’objectif : une vue partagée de tous les e-mails. À cette étape, rien ne touche à la production.

Chaque phase est utile en soi, et vous pouvez vous arrêter après n’importe laquelle.
Le serveur MCP de Brew se trouve à l’adresse https://brew.new/api/mcp et utilise OAuth : vous vous connectez avec Brew et choisissez la marque dans laquelle l’agent peut travailler. Dans Claude Code :
claude mcp add --transport http brew "https://brew.new/api/mcp"Cette commande n’enregistre le serveur que dans la configuration locale de ce projet. Pour l’utiliser dans tous vos projets, ajoutez --scope user. Avant d’utiliser ses outils, lancez claude mcp login brew, ou ouvrez /mcp et authentifiez la connexion Brew.
La documentation de configuration des clients couvre aussi Cursor et Codex. Les clients sans OAuth peuvent utiliser une clé API limitée à une marque. Demandez ensuite à l’agent d’appeler get_brew_capabilities pour qu’il lise la liste à jour des outils au lieu de la deviner.
Demandez une liste à l’agent :
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.Gardez la section « Unknown » (les cas non résolus). Les confirmations d’authentification et les reçus Stripe ne sont pas des appels d’envoi dans votre code, mais ils ont leur place dans la liste. Commitez EMAILS.md. Si vous vous arrêtez là, vous disposez déjà d’une liste que vous n’aviez pas la veille.
La meilleure source pour l’import, c’est le HTML que votre code produit déjà. L’utilitaire render de React Email vous fournit cette chaîne :
import { render } from 'react-email'
import WelcomeEmail from './emails/welcome'
const html = await render(
<WelcomeEmail firstName="Ana" planName="Pro" trialDays={14} />
)Les projets plus anciens importent render depuis @react-email/render. Utilisez des données de test réalistes, pas "test", puisque votre équipe va relire ces e-mails. Demandez à l’agent un script qui fait le rendu de chaque modèle dans un fichier.
Brew importe aussi directement un module React Email avec format: "jsx", en le lisant de façon statique, sans l’exécuter. Les props prennent leurs valeurs par défaut ou celles de PreviewProps, les composants importés depuis d’autres fichiers locaux sont ignorés ou rejetés, et await et les constructions similaires sont refusés. Au-delà d’un fichier unique et autonome, utilisez le HTML rendu.
Importez ensuite chaque rendu avec import_email, en indiquant un groupName par grande partie du produit :
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.Les développeurs se demandent, à juste titre, si l’import réécrit leurs e-mails. Ce n’est pas le cas :
assetReport liste celles qu’il n’a pas pu récupérer.baseUrl sert uniquement à résoudre les chemins d’images relatifs.Chaque groupe a son canevas. Ouvrez brew.new/emails/onboarding : toute la séquence s’affiche côte à côte, avec une bascule ordinateur/mobile et des commentaires sur chaque design. Les liens vers le canevas fonctionnent pour les personnes connectées à votre espace de travail Brew. Il n’existe pas de lien de partage public : invitez donc vos relecteurs.
C’est là que les problèmes apparaissent : deux logos, un bouton au lien mort, trois pieds de page. Lancez audit_email avant de corriger quoi que ce soit. Il contrôle les liens, les images, la conformité, le poids chargé, la compatibilité avec les clients de messagerie, l’accessibilité et les textes, coûte 5 crédits par audit complet, et accepte un emailId enregistré ou du HTML brut : vous pouvez donc auditer des e-mails que vous n’avez pas importés. Notre checklist de contrôle qualité avant envoi détaille chaque contrôle et chaque seuil.
Vous disposez maintenant d’un inventaire, de tous vos e-mails sur un canevas et d’une liste de problèmes, et votre code envoie toujours tout comme avant.
Désormais, Brew envoie certains e-mails à la place de votre code. Tous les e-mails n’ont pas besoin de migrer, et à tout moment, un seul système envoie un type d’e-mail donné.
| Aujourd’hui dans votre code | Dans Brew |
|---|---|
resend.emails.send({ react: <WelcomeEmail /> }) |
Un événement déclencheur associé à une automatisation publiée qui comporte une étape « Envoyer un e-mail » |
| Les props passées au composant | Les champs du payload du déclencheur, utilisés comme balises de fusion, par exemple {{ firstName | there }} ou {{ trigger.planName }} |
Le domaine du from |
Un domaine d’envoi vérifié dans Brew |
| Votre table d’utilisateurs | Les contacts, créés via l’API REST ou une intégration |
| Un job cron qui envoie une séquence | Une automatisation avec des étapes « Attente », « Filtre » et « Envoyer un e-mail » |
L’agent appelle create_domain pour obtenir les enregistrements DNS, puis verify_domain une fois qu’ils sont en ligne. Les domaines créés via MCP ou l’API sont des domaines marketing. Pour les réinitialisations de mot de passe et les reçus, configurez dans l’application Brew un domaine à usage transactionnel : il omet le pied de page de désabonnement et envoie aussi aux contacts désabonnés. La documentation sur la vérification de votre domaine d’envoi détaille les enregistrements.
MCP met à jour les contacts mais ne les crée pas. Créez-les depuis votre backend avec POST /v1/contacts, qui crée ou met à jour un contact ou un lot de 1 000 contacts au maximum et crée automatiquement les champs personnalisés, ou importez un CSV dans l’application. Actionner un déclencheur crée ou met aussi à jour le contact présent dans son payload. N’importez que des personnes qui ont accepté d’avoir de vos nouvelles. La documentation sur l’ajout de contacts explique ce que Brew attend.
Un détail facile à rater : l’e-mail de bienvenue importé dit littéralement « Hi Ana ». Remplacez chaque valeur de test par une balise de fusion comme {{ firstName | there }}, où le texte après la barre verticale est la valeur par défaut. Utilisez l’éditeur de Brew, ou demandez à l’agent de lancer edit_email en se limitant à ces remplacements. C’est une modification par IA qui consomme des crédits : vérifiez donc l’aperçu. La page sur les balises de fusion détaille la syntaxe.
L’agent crée un déclencheur avec save_trigger. Le schéma du payload doit inclure l’email du destinataire. Donnez-lui un contrat typé (infer_payload_contract en rédige un à partir d’un exemple de payload, set_trigger_contract l’enregistre), puis récupérez-le avec get_trigger_contract au format ts ou zod pour que votre backend et Brew s’accordent sur la forme du payload.
save_automation construit ensuite le déclencheur et une étape « Envoyer un e-mail » avec l’e-mail, le domaine et l’objet. L’automatisation reste à l’état de brouillon jusqu’à ce que vous la publiiez. dryRun valide le graphe, test_automation envoie une copie réelle à votre adresse, et check_trigger confirme qu’une automatisation publiée est à l’écoute avant que la production n’actionne quoi que ce soit.
C’est la seule modification de votre code applicatif. Avant, avec 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} />,
})Après, avec 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 se résout même quand la requête est refusée : vérifiez donc res.ok et laissez votre gestionnaire de jobs réessayer ou déclencher une alerte. L’endpoint renvoie 202 quand il accepte l’événement et 422 si aucune automatisation publiée n’écoute le déclencheur.
Construisez l’Idempotency-Key à partir d’un identifiant stable, comme celui de l’utilisateur ou de la commande. Une clé répétée renvoie l’exécution d’origine au lieu d’envoyer deux fois, et réutiliser une clé avec un corps différent renvoie 409 IDEMPOTENCY_CONFLICT. Brew conserve la clé d’un déclenchement aussi longtemps que son enregistrement de réception, soit 90 jours, et non les 24 heures de nombreuses API. Considérez les clés comme permanentes, une par action. Une clé fondée sur un horodatage change à chaque nouvelle tentative, et une clé réutilisée pour une autre action des semaines plus tard peut être rejouée au lieu d’être envoyée.
Le code de production appelle cet endpoint avec une clé API, pas via MCP. Sur une connexion OAuth, MCP demande à une personne de confirmer les envois réels, les déclenchements et les publications : parfait dans une conversation, inadapté à un gestionnaire de requêtes. Le guide MCP ou REST détaille cette répartition.
EMAILS.md.Le guide de migration depuis Loops suit la même logique.
Les e-mails de confirmation et de lien magique de Supabase continuent de partir de Supabase. L’intégration Supabase de Brew écoute les événements utilisateur pour lancer des automatisations, sans remplacer les e-mails de Supabase Auth. Une facture détaillée, construite à partir de données complexes au moment de l’envoi, peut aussi rester plus simple dans le code : vérifiez d’abord ce dont vos balises de fusion auraient besoin. Gardez des copies importées sur le canevas pour que ces e-mails restent visibles.
Auditez l’ensemble. Lancez audit_email sur tout un groupe, corrigez, puis relancez-le avant les gros envois.
Vérifiez sur de vrais clients de messagerie. test_email_rendering renvoie des captures d’écran issues de clients de messagerie et d’appareils précis, mode sombre compris, pour 10 crédits par exécution. create_inbox_placement_test envoie une copie réelle à des boîtes de réception témoins et indique où elle a atterri, pour 10 crédits également.
Harmonisez l’ensemble. Corrigez les incohérences dans l’éditeur, ou demandez à l’agent d’appliquer une modification, comme un nouveau pied de page, à tout un groupe avec edit_email.
Lisez les résultats. get_email_analytics rend compte des envois et de l’engagement. list_insights renvoie les constats que Brew a détectés dans votre compte, chacun avec les métriques sur lesquelles il repose.
Testez des variantes de façon délibérée. Créez des variantes sur le canevas et orientez les contacts avec une étape « Embranchement » fondée sur leur comportement, par exemple s’ils ont cliqué. Brew ne désigne pas pour vous le gagnant d’une répartition aléatoire : comparez donc les variantes vous-même.
Gardez les nouveaux e-mails visibles. Ajoutez une ligne à AGENTS.md ou à un fichier équivalent : les nouveaux e-mails produit sont créés dans Brew, envoyés par un déclencheur et ajoutés à EMAILS.md dans la même pull request.
Oui. import_email accepte du HTML rendu, du MJML, un message .eml enregistré ou un module React Email. Le HTML rendu est l’option la plus fiable, car un module est lu de façon statique : les props prennent leurs valeurs par défaut ou d’aperçu, et les composants importés depuis d’autres fichiers locaux sont laissés de côté.
Non. Il n’existe ni intégration, ni import, ni export Resend. Vous importez le HTML que produit votre code et, si vous migrez, votre code actionne un déclencheur Brew au lieu d’appeler Resend.
Non. Utilisez MCP depuis un agent de code pour la configuration, les imports, les audits et les tests. Le code de production doit appeler l’API REST avec une clé API, car sur les connexions OAuth, MCP demande à une personne de confirmer les envois réels et les déclenchements.
L’import convertit l’e-mail en design Brew modifiable et conserve le HTML source d’origine pour l’envoi. Il retire les scripts, les iframes, les formulaires et les gestionnaires d’événements, neutralise les pixels de suivi existants et réhéberge les images publiques. Relisez chaque e-mail sur le canevas, en vue ordinateur et en vue mobile, avant de l’envoyer depuis Brew.
