@suaveplan/email-templates - Universal React-free email template engine: VNode factories, nine reusable components, five built-in templates (welcome, verification, password-reset, notification, invoice), typed registry, fluent builder, theme system, structured errors, OTel instruments. Produces email-safe HTML strings with inline styles; runs in Bun, Node, and browser.
Universal, React-free email template engine. Produces email-safe HTML strings with inline styles via VNode factories — runs identically in Bun, Node, and the browser.
Documentation tree
- email-button —
EmailButtonis the canonical call-to-action surface in an email body — a table-wrapped<a>with variant-driven them…- email-button —
EmailButtonis the canonical call-to-action surface in an email body — a table-wrapped<a>with variant-driven them…
- email-button —
- email-container —
EmailContainergroups related content inside an email body — a callout box, an info banner, a code-card. It emits a s…- email-container —
EmailContainergroups related content inside an email body — a callout box, an info banner, a code-card. It emits a s…
- email-container —
- email-divider — A horizontal divider rendered as a single-row
<table>whose<td>carriesborder-top: 1px solid <color>. The table…- email-divider — A horizontal divider rendered as a single-row
<table>whose<td>carriesborder-top: 1px solid <color>. The table…
- email-divider — A horizontal divider rendered as a single-row
- email-footer — Renders the email footer block — company copyright, optional address, optional list of inline links (typically Privacy…
- email-footer — Renders the email footer block — company copyright, optional address, optional list of inline links (typically Privacy…
- email-heading — Renders an
<h1>…<h6>element with a level-keyed font-size and line-height schedule tuned for inbox-rendering ergono…- email-heading — Renders an
<h1>…<h6>element with a level-keyed font-size and line-height schedule tuned for inbox-rendering ergono…
- email-heading — Renders an
- email-image — Renders an
<img>inside a centring<table>with the canonical responsive-email defaults (display:block, `max-widt…- email-image — Renders an
<img>inside a centring<table>with the canonical responsive-email defaults (display:block, `max-widt…
- email-image — Renders an
- email-layout —
EmailLayoutis the root VNode every email template wraps its body in. It emits a 100%-width<table>with a themed m…- email-layout —
EmailLayoutis the root VNode every email template wraps its body in. It emits a 100%-width<table>with a themed m…
- email-layout —
- email-link — Themed inline
<a>link with safe defaults (target="_blank",rel="noopener noreferrer") for body-copy hyperlinks.…- email-link — Themed inline
<a>link with safe defaults (target="_blank",rel="noopener noreferrer") for body-copy hyperlinks.…
- email-link — Themed inline
- email-text — Paragraph component for email-body copy.
EmailTextemits a themed<p>with one of three size variants (body/ `ca…- email-text — Paragraph component for email-body copy.
EmailTextemits a themed<p>with one of three size variants (body/ `ca…
- email-text — Paragraph component for email-body copy.
- error-codes — Stable error-code registry for
@suaveplan/email-templates. Every failure raised by the package extends `SuaveplanErro…- error-codes — Stable error-code registry for
@suaveplan/email-templates. Every failure raised by the package extends `SuaveplanErro…
- error-codes — Stable error-code registry for
- message —
createEmailMessageglues the renderer to the addressing envelope, producing anEmailMessageResultplain object suit…- message —
createEmailMessageglues the renderer to the addressing envelope, producing anEmailMessageResultplain object suit…
- message —
- renderer — The renderer is the bridge between the
EmailTemplate<TProps>contract and a final{ html, text, subject }triple re…- renderer — The renderer is the bridge between the
EmailTemplate<TProps>contract and a final{ html, text, subject }triple re…
- renderer — The renderer is the bridge between the
- telemetry — Exposes the OpenTelemetry instrument set published by
@suaveplan/email-templates. Every public render or registry mut…- telemetry — Exposes the OpenTelemetry instrument set published by
@suaveplan/email-templates. Every public render or registry mut…
- telemetry — Exposes the OpenTelemetry instrument set published by
- template-builder —
TemplateBuilderis a fluent API for assembling anEmailTemplate<TProps>value step-by-step. It exists because const…- template-builder —
TemplateBuilderis a fluent API for assembling anEmailTemplate<TProps>value step-by-step. It exists because const…
- template-builder —
- template-registry —
TemplateRegistryis a type-safe in-memory store forEmailTemplatevalues keyed by name. It supports per-name lookup…- template-registry —
TemplateRegistryis a type-safe in-memory store forEmailTemplatevalues keyed by name. It supports per-name lookup…
- template-registry —
- invoice — The
invoiceTemplateis the receipt / invoice / order-confirmation email. It renders a heading carrying the invoice nu…- invoice — The
invoiceTemplateis the receipt / invoice / order-confirmation email. It renders a heading carrying the invoice nu…
- invoice — The
- notification — The
notificationTemplateis the generic system-notification email — a configurable severity callout suitable for prod…- notification — The
notificationTemplateis the generic system-notification email — a configurable severity callout suitable for prod…
- notification — The
- password-reset — The
passwordResetTemplateis the canonical password-reset message. It explains the request, exposes a reset CTA, comm…- password-reset — The
passwordResetTemplateis the canonical password-reset message. It explains the request, exposes a reset CTA, comm…
- password-reset — The
- verification — The
verificationTemplateis the standard email-address verification flow message. It greets the recipient, optionally…- verification — The
verificationTemplateis the standard email-address verification flow message. It greets the recipient, optionally…
- verification — The
- welcome — The
welcomeTemplateis the canonical post-signup onboarding email. It greets the recipient by name, summarises why th…- welcome — The
welcomeTemplateis the canonical post-signup onboarding email. It greets the recipient by name, summarises why th…
- welcome — The
- theme — Provides the theme tokens consumed by every email component — colours, typography, spacing, branding, border-radius, an…
- theme — Provides the theme tokens consumed by every email component — colours, typography, spacing, branding, border-radius, an…
- vnode — Defines the universal VNode primitive — a
{ tag, attrs, children }triple plus a pure-string HTML renderer — tha…- vnode — Defines the universal VNode primitive — a
{ tag, attrs, children }triple plus a pure-string HTML renderer — tha…
- vnode — Defines the universal VNode primitive — a
What's included
- Nine reusable components —
EmailLayout,EmailContainer,EmailHeading,EmailText,EmailLink,EmailImage,EmailDivider,EmailButton,EmailFooter. - Five built-in templates —
welcomeTemplate,verificationTemplate,passwordResetTemplate,notificationTemplate,invoiceTemplate. - VNode core —
h(tag, attrs, children)hyperscript factory and a pure-stringrenderVNodewalker. - Renderer —
renderToHtml(template, props, options?)→{ html, text, subject }with OTel instrumentation. - Theme system —
defaultTheme,createTheme,mergeThemes. - Type-safe registry —
TemplateRegistry<TMap>with category / tag / author search. - Fluent builder —
TemplateBuilder<TProps>/createTemplateBuilder<TProps>(). - Adapter —
createEmailMessage(template, props, recipient, options?)returning a plain-object envelope ready for SMTP / SES / SendGrid. - Structured errors —
EmailTemplatesErrorwith sixEMAIL_TEMPLATES.*codes.
Quick start
import {
createEmailMessage,
welcomeTemplate,
} from "@suaveplan/email-templates";
const message = createEmailMessage(
welcomeTemplate,
{ recipientName: "Jane", ctaUrl: "https://app.example.test/get-started" },
{ to: "jane@example.test", from: "hello@suaveplan.com" },
);
await mailer.send(message);
Architecture
Upstream @suaveplan/email-templates was a React component library
rendered via react-dom/server. The port honours the enterprise
spec §3 ("Zero browser / Node / React dependencies") by re-implementing
the full upstream surface as VNode factories — pure functions
returning { tag, attrs, children } triples walked by a single
HTML-emitter (renderVNode).
The renderer is the sole point at which child text is HTML-escaped and attributes are serialised. Components emit data; escaping happens once.
Universal
- Zero React / DOM / Node-specific dependencies at runtime.
- Injectable
Clock(@suaveplan/types) for deterministic footer year. - OTel instruments via
@opentelemetry/api. - Pure-TypeScript implementation, 100% statement / branch / function / line coverage.
Sub-path exports
@suaveplan/email-templates/vnode, …/theme, …/renderer, …/message,
…/template-builder, …/template-registry, …/components, …/templates,
…/errors, …/otel — each exposes a focused slice of the surface for
tree-shake friendliness.