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
nameLabel shown in the UI.
slugStable identifier used by templateSlug. Lowercase letters, numbers, hyphens.
subjectMay contain Handlebars placeholders.
htmlBodyThe HTML body with Handlebars placeholders.
textBodyOptional plain-text fallback.
domainIdOptionally 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": "alex@example.com","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": "alex@example.com", "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": "hello@yourdomain.com","to": "alex@example.com","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.