Templates

Email templates with Handlebars,
or one of 50 built-in layouts.

Store custom templates with variables, loops, and conditionals — or reference a React Email layout and switch themes per send. Every template is sent bytemplateSlug.

Custom templates

#custom

A custom template is an HTML body (with an optional plain-text fallback) that you create and store. Reference it by its slug.

FieldRequiredNotes
name✅Label shown in the UI.
slug✅Stable identifier used by templateSlug. Lowercase letters, numbers, hyphens.
subject✅May contain Handlebars placeholders.
htmlBody✅The HTML body with Handlebars placeholders.
textBody—Optional plain-text fallback.
domainId—Optionally scope the template to a domain.
⚡Slugs are mandatory. If the slug you pick already exists, EmailFlare appends a short suffix to keep it unique — always read the create response for the final slug.

Variables

#variables

Insert values with double curly braces, then pass them via variables on /v1/send:

<p>Hi {{name}},</p><p>Order <strong>{{orderId}}</strong> is on its way.</p>
{"to": "[email protected]","templateSlug": "order-confirmation","variables": { "name": "Alex", "orderId": "ORD-1042" }}
💡If a variable is missing from the payload, it renders as an empty string — not as a literal {{name}} placeholder.

Loops & conditionals

#logic

Custom templates render with Handlebars, so the full block syntax is available:

{{#if items}}<ul>{{#each items}}<li>{{name}} — {{price}}</li>{{/each}}</ul>{{else}}<p>Your cart is empty.</p>{{/if}}

variables accepts nested objects and arrays, so the example above works with:

{"templateSlug": "cart-summary","variables": {"items": [{ "name": "Widget", "price": "$9.00" },{ "name": "Gadget", "price": "$14.50" }]}}

Built-in helpers ({{#unless}}, {{#with}}, …) are all available.

Styling

#styling

Custom templates use inline CSS — write styles directly in the HTML body. This is the standard approach for HTML email and the most reliable across email clients:

<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;"><h1 style="color: #f97316;">Hello {{name}}</h1><p style="color: #333; line-height: 1.6;">Your order {{orderId}} is confirmed.</p></div>

There is no separate theme system for custom templates — themeId on /v1/send only applies to built-in React Email layouts. For reusable styling, you have a few options:

Style variables

Pass colours and fonts as template variables:

<h1 style="color: {{primaryColor}}; font-family: {{font}};">Hello {{name}}</h1>
{ "variables": { "name": "Alex", "primaryColor": "#f97316", "font": "Arial, sans-serif" } }

Theme object with {{#with}}

Pass a nested theme object and scope into it:

{{#with theme}}<div style="background: {{bg}}; color: {{text}};"><h1 style="color: {{primary}};">Hello {{../name}}</h1></div>{{/with}}
{"variables": {"name": "Alex","theme": { "primary": "#f97316", "bg": "#fafafa", "text": "#333" }}}

Base layout in the template

Put your wrapper HTML (header, footer, brand styles) directly in each template body. Since templates are stored per-slug, you can copy-paste a consistent base layout across templates.

Built-in layouts

#layouts

EmailFlare seeds 50 system templates — one per React Email layout — on first run. Their HTML body is empty because the layout is the content. Reference them by slug exactly like custom templates:

{ "to": "[email protected]", "templateSlug": "welcome", "variables": { "name": "Alex", "appName": "Acme" } }

Themes

Layout templates support colour themes via themeId. Switch per send — no CSS edits needed.

default
ocean
forest
violet
slate
⚡themeId only applies to layout templates. Custom HTML templates ignore it — you control styling directly in the body.

Managing templates

#managing

Create and edit templates from the Templates page in the admin UI — the live preview highlights resolved variables inline. Or use the admin API (session-authenticated /api/templates):

GET /api/templates # list templatesGET /api/templates/:idOrSlug # fetch one (by id or slug)POST /api/templates # createPUT /api/templates/:id # updateDELETE /api/templates/:id # deletePOST /api/templates/:id/preview # render with variables + optional themeId

Create example:

{"name": "Order confirmation","slug": "order-confirmation","subject": "Your order {{orderId}} is confirmed","htmlBody": "<p>Hi {{name}},</p><p>Order {{orderId}} is confirmed.</p>","textBody": "Hi {{name}}, your order {{orderId}} is confirmed."}

Sending with a template

#sending

Send by slug (preferred) or by id:

POST https://your-emailflare.com/v1/sendAuthorization: Bearer eflive_xxx{"from": "[email protected]","to": "[email protected]","templateSlug": "order-confirmation","variables": { "name": "Alex", "orderId": "ORD-1042" }}
  • subject on the send payload overrides the template subject.
  • variables are applied to both the subject and the body.
  • At least one of templateSlug, templateId, html, or text must be present.
  • Test keys (eftest_) capture the rendered email into the Test Mailbox — verify without burning real delivery.

Keep going

More EmailFlare reference material.