Resend
Configure, sendEmail, handler de invoke.
A integração Resend é mínima: configure com sua API key, depois envie emails do server. Pensada para emails transacionais (confirmação de pedido, reset de senha, alertas) — não para marketing em massa.
Install
Já está em @decocms/apps .
Configure
.deco/blocks/deco-resend.json :
{
"__resolveType": "deco-resend",
"apiKey": { "__resolveType": "secret/key" },
"from": "Loja <[email protected]>",
"replyTo": "[email protected]"
}
from deve ser um endereço em domínio verificado no Resend.
Wiring
import { initResendFromBlocks } from "@decocms/apps/resend/client";
createSiteSetup({
// ...
initPlatform: () => {
initVtexFromBlocks();
initResendFromBlocks();
},
});
Se sua loja usa multiple init helpers, encadeie em initPlatform .
Enviando email
import { sendEmail } from "@decocms/apps/resend/sdk";
await sendEmail({
to: "[email protected]",
subject: "Pedido confirmado",
html: "<h1>Obrigado!</h1>",
});
A função:
- Lê
apiKey,from,replyTodo block configurado. - Posta para
https://api.resend.com/emails. - Lança em status não-2xx.
Handler de invoke
@decocms/apps/resend/handlers/sendEmail.ts é uma action invocável:
// do client (raro — geralmente server-side):
await invoke["resend/actions/sendEmail.ts"]({
to: "...",
subject: "...",
html: "...",
});
Use server-side em sua maioria — expor envio de email arbitrário ao client é vetor de spam.
Padrões
Email de confirmação de pedido
import { sendEmail } from "@decocms/apps/resend/sdk";
import { renderOrderConfirmationHtml } from "~/emails/orderConfirmation";
const handleOrder = async (order) => {
await persistOrder(order);
await sendEmail({
to: order.email,
subject: `Pedido #${order.id} confirmado`,
html: renderOrderConfirmationHtml(order),
});
};
Templates
A integração não vem com sistema de template. Use renderToString do React para emails baseados em React, ou embuta strings de template com placeholders.
import { renderToString } from "react-dom/server";
function OrderEmail({ order }: { order: Order }) {
return (
<html>
<body>
<h1>Obrigado por comprar com a gente!</h1>
<p>Pedido #{order.id}</p>
</body>
</html>
);
}
const html = renderToString(<OrderEmail order={order} />);
Domínio verificado obrigatório
Resend exige domínio verificado para from . No dashboard Resend, adicione registros DNS, espere verificação. Sem isso, todos os emails ficam pendentes/falham.
Erros
sendEmail lança em status não-2xx com a mensagem do Resend. Logue contra seu coletor de erro:
try {
await sendEmail({ ... });
} catch (err) {
console.error("[resend]", err);
// não lance para o user — falha de email não deve quebrar o fluxo
}
Tracing
Toda chamada de sendEmail pega seu próprio span via createInstrumentedFetch("resend") (o framework conecta automaticamente). Apareça em wrangler tail como resend.send_email .
Limites
- Plano free: 100 emails/dia, 3.000/mês.
- Plano grátis: 1 domínio verificado.
- Rate limit: 10 req/sec; busts trocam para 429.
Para volumes maiores, migre para plano pago Resend ou para outro provider (SES, Postmark) — wiring é o mesmo, só troca de URL/auth.
Sem hooks client-side
Não há useEmail hook. Email é trabalho server-side; chame sendEmail ou actions invocáveis a partir de loaders/middleware/server functions.
Veja também
Found an error or want to improve this page?
Edit this page