Resend Email

Configure Resend for transactional delivery and native batch sending.

Use Resend when you want a simple transactional API, template variables, and native batch sending. ViteHub maps the shared email surface to Resend so your email definitions stay portable.

Install the SDK

Terminal
pnpm add https://pkg.pr.new/vite-hub/vitehub/@vitehub/email@main resend

Set RESEND_API_KEY or RESEND_API_TOKEN in the runtime environment, or pass email.apiKey directly in config.

Configure Resend

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@vitehub/email/nuxt'],
  email: {
    provider: 'resend',
    apiKey: process.env.RESEND_API_KEY,
    defaults: {
      from: 'Acme <hello@example.com>',
    },
  },
})

Send with Resend

Start with sendEmail(...) when you are sending an email file you defined in your app. Pass template input as the second argument and send-time recipients in the third.

await sendEmail('welcome', {
  name: 'Max',
}, {
  to: 'max@example.com',
  delivery: {
    labels: ['welcome'],
    idempotencyKey: 'welcome:max',
  },
})

Drop to createEmailClient() when you need already-rendered payloads or manual batch sends.

const email = await createEmailClient()

await email.send({
  from: 'Acme <hello@example.com>',
  to: 'max@example.com',
  subject: 'Welcome',
  html: '<p>Welcome</p>',
  text: 'Welcome',
  delivery: {
    labels: ['welcome'],
    scheduleAt: new Date(Date.now() + 60_000),
    idempotencyKey: 'welcome:max',
    template: {
      key: 'welcome-template',
      data: { name: 'Max' },
    },
  },
})

What changes on Resend

ConcernBehavior
delivery.labelsViteHub maps labels to Resend tags.
delivery.template.keyA numeric key becomes template.id. A string key becomes template.alias.
delivery.template.dataViteHub maps template data to template.variables.
delivery.scheduleAtViteHub passes the schedule through Resend's scheduledAt send option.
delivery.idempotencyKeyViteHub passes the value through Resend's idempotencyKey send option.
Batch sendingViteHub uses Resend's native batch path when the SDK exposes batch.send(). Otherwise it falls back to fanout sends.

Use delivery.transport for Resend-only payload fields such as batch-only options like validationMode.

const email = await createEmailClient()

await email.sendBatch([
  {
    from: 'Acme <hello@example.com>',
    to: 'max@example.com',
    subject: 'Hello',
    html: '<p>Hello</p>',
    delivery: {
      transport: {
        validationMode: 'strict',
      },
    },
  },
])
Choose Resend when you want the shortest path from a Markdown definition to a hosted transactional email API with good batch support.