Templates
Register a template
Section titled “Register a template”Use outbound.template(name, options) on a send Email instance.
const welcome = outbound.template<{ user: { name: string } }>("welcome", { subject: ({ user }) => `Welcome ${user.name}`, text: ({ user }) => `Hello ${user.name}. Welcome to our app.`, html: ({ user }) => `<p>Hello ${user.name}. Welcome to our app.</p>`,})The template name must contain only letters, numbers, dot, underscore, or dash. The method returns the normalized name.
Render modes
Section titled “Render modes”Templates use one of two render modes:
- static — content is rendered once at compile time. Use when the template content is fixed and does not depend on the send payload.
- dynamic — content is rendered at send time with the payload. Use when the template content depends on send payload values.
Layeron detects the mode automatically:
- A string
subject,text, orhtmlproduces a static template. - A function
subject,text, orhtmlproduces a dynamic template. - A React component with no parameters (
component.length === 0) is static. - A React component that accepts a payload parameter is dynamic.
Override auto-detection with render: "static" or render: "dynamic".
String templates
Section titled “String templates”Static string templates render at compile time.
const notice = outbound.template("notice", { subject: "Service update", text: "Our service will be down for maintenance at midnight.",})Dynamic string templates use a payload function. Payload values are resolved at send time.
const receipt = outbound.template<{ amount: number }>("receipt", { subject: ({ amount }) => `Receipt for $${amount}`, html: ({ amount }) => `<p>Your payment of $${amount} was received.</p>`,})Placeholder syntax
Section titled “Placeholder syntax”Static template strings can use {{path.to.value}} placeholders. Layeron
replaces them with values from the send payload.
const welcome = outbound.template("welcome", { subject: "Welcome {{user.name}}", text: "Hello {{user.name}}. Welcome to {{app.name}}.",})const result = await outbound.send({ from: "hello", to: "ada@example.com", template: "welcome", payload: { user: { name: "Ada" }, app: { name: "Layeron" }, },})Placeholder paths use dot notation. If a path is missing from the payload, sending fails with an error.
In HTML templates, placeholder values are HTML-escaped automatically.
React Email templates
Section titled “React Email templates”Pass a React Email component with react or component.
import { Body, Html, Text } from "@react-email/components"
function WelcomeEmail({ user }: { user: { name: string } }) { return ( <Html> <Body> <Text>Hello {user.name}</Text> </Body> </Html> )}
const welcome = outbound.template<{ user: { name: string } }>("welcome", { render: "dynamic", subject: ({ user }) => `Welcome ${user.name}`, text: ({ user }) => `Hello ${user.name}`, react: WelcomeEmail,})Static React components
Section titled “Static React components”Use render: "static" for a React component that does not read the payload.
The component renders once at compile time and reuses the same HTML for every
send.
function Footer() { return ( <Html> <Body> <Text>Thanks for using our service.</Text> </Body> </Html> )}
const footer = outbound.template("footer", { render: "static", react: Footer,})Dynamic React components
Section titled “Dynamic React components”Dynamic React Email components render at send time with the payload. Use this for personalized content.
function InvoiceEmail({ customer, total }: { customer: string; total: number }) { return ( <Html> <Body> <Text>Dear {customer},</Text> <Text>Your invoice for ${total} is ready.</Text> </Body> </Html> )}
const invoice = outbound.template("invoice", { subject: ({ customer }) => `Invoice for ${customer}`, react: InvoiceEmail,})The React component renders to HTML, and Layeron generates a plain text version from the HTML output.
Template overrides at send time
Section titled “Template overrides at send time”subject, text, and html in outbound.send(input) override the matching
field from the registered template.
const result = await outbound.send({ from: "hello", to: "ada@example.com", template: "welcome", payload: { user: { name: "Ada" } }, subject: "Special welcome for Ada", // overrides template subject})Template requirements
Section titled “Template requirements”Every template must provide at least one of subject, text, html,
react, or component. Sending fails at runtime when the resolved message
lacks a subject or body content.
Local dev behavior
Section titled “Local dev behavior”Local dev stores the rendered template output in the outbox JSON file. Template rendering behavior is the same as production — static templates render once, dynamic templates render per send.