zazzy
Features

Transactional email

Resend + react-email templates, dispatched through jobs.

Transactional email pairs Resend with react-email templates, sent asynchronously through the jobs feature. Product code never calls the transport directly: it enqueues an email/send event with a registry-checked template name and typed props, and the job renders and delivers it — with an idempotency ledger guaranteeing at most one delivery per key.

Optional feature

Email is optional (core: false, requires: ["jobs"]). When it's pruned, auth/orgs' marked send sites fall back to a console transport, so those flows keep working — just logged instead of delivered.

What it does

  • Public surfaceenqueueEmail({ to, template, props, idempotencyKey }) dispatches an email/send event; emailIdempotencyKey(template, seed) derives a stable, per-send key so a retried mutation can't double-send.
  • Template registry — typed react-email templates (emails/registry.tsx, layout.tsx) so a template name and its props are checked at compile time.
  • Send job — the email/send Inngest function renders the template and calls Resend, recording the key in the dedup ledger first.
  • Previewsemail:dev runs react-email's preview server over features/email/previews/*.

Models it adds

ModelPurpose
EmailDispatchThe email/send idempotency ledger — a unique idempotencyKey per delivery, so a replayed event sends nothing.

It's a dedup ledger, not an inspection log: it stores the key plus enough to debug a collision, not message bodies.

Env it needs

RESEND_API_KEY=    # Resend API key
EMAIL_FROM=        # default From address

Adds the email:dev script (react-email preview server).

Composition

  • requires: ["jobs"] — sends flow through the email/send event.
  • auth and orgs are soft consumers: verification, magic-link, reset, and org-invite templates are enqueued at @feature:email-marked call sites, with a console fallback when email is absent. (The auth/orgs emails/ directories are owned by the email feature and prune with it.)
  • billing requires: ["email"] — receipt and payment-failed emails.
  • usage sends a quota-warned email through the injected email surface.

What pruning removes

Leaving email out drops features/email, the auth/emails and orgs/emails template dirs, the EmailDispatch model, and the email/send job. Marked call sites in auth/orgs revert to the console transport. Because billing requires email, deselecting email also deselects billing (and its dependents flags, usage, admin, marketing).

On this page