Resend Integration
Render React Email templates, send with Resend, schedule messages, preview templates, and receive webhooks.
Define templates
import { resend, template } from "@farm.js/email";
const templates = {
welcome: template({
subject: "Welcome to Farm",
component: ({ name }: { name: string }) => <p>Hello {name}</p>,
}),
};
export const email = resend({
apiKey: process.env.RESEND_API_KEY,
defaults: { from: "hello@example.com" },
templates,
});Choose SDK ownership
Let Farm construct Resend
The example above is the default path. When instance is omitted, Farm creates the Resend SDK from
apiKey, supplied directly or through RESEND_API_KEY.
Provide an application-owned instance
import { Resend } from "resend";
import { resend } from "@farm.js/email";
const resendClient = new Resend(process.env.RESEND_API_KEY);
export const email = resend({
instance: resendClient,
defaults: { from: "hello@example.com" },
templates,
});The instance wins if an API key is also supplied. Templates, defaults, scheduling, previews, routes, and webhooks remain integration options in either mode.
Send mail
await apiClient.email.send.post({
body: {
template: "welcome",
to: "ada@example.com",
data: { name: "Ada" },
},
});What Resend adds
| Area | Details |
|---|---|
| Templates | Typed React Email templates with subjects, preview text, defaults, and preview props. |
| Send | A typed send route for transactional messages. |
| Schedule | A typed route for future delivery. |
| Preview | HTML and text rendering for local previews or admin tools. |
| Templates index | A route that lists configured templates and preview metadata. |
| Webhooks | Optional Resend webhook receivers for delivery events. |
Preview before sending
const preview = await api.email.preview.post({
body: {
templateId: "welcome",
data: {
name: "Ada",
},
},
});
console.log(preview.data?.subject);
console.log(preview.data?.html);Schedule mail
await api.email.schedule.post({
body: {
templateId: "welcome",
to: "ada@example.com",
when: "tomorrow 9am",
data: {
name: "Ada",
},
},
});Template defaults
Templates can supply their own subject, previewText, from, and replyTo. The integration also supports global defaults, which keeps common sender details out of every call.
const templates = {
invite: template({
subject: ({ workspace }: { workspace: string }) => `Join ${workspace}`,
previewText: "You were invited to collaborate.",
component: ({ workspace }: { workspace: string }) => <p>Join {workspace}</p>,
}),
};Production notes
- Set
RESEND_API_KEYand a verifiedRESEND_FROM_EMAIL. - Use idempotency keys for important transactional flows.
- Preview templates in development before sending them to real recipients.
- Keep template IDs stable because they are part of the caller contract.
- Verify webhooks before using delivery events for product logic.