Skip to Content
Email MarketingBuild Templates

Build Email Templates

Templates are reusable email designs. Build one with the visual editor, then send it to any audience from a campaign — or one-to-one via the public API.

Cross-client compatibility: templates compile through react-email  (the same library Resend ships) so the final HTML works across Gmail, Outlook, Apple Mail, Yahoo, and mobile clients without you hand-rolling table-based markup.

When to use a template

  • Sending the same email shape repeatedly (order confirmations, OTP codes, password resets)
  • Marketing campaigns where the design should be consistent across sends
  • Anything you want non-developers on your team to update without redeploying

For one-off sends with bespoke HTML, the public API /email/send endpoint takes inline HTML directly — no template needed.

Open the editor

Email → Templates New template.

A blank template opens with three default blocks (heading, text, footer) so you have something to edit immediately.

Editor layout

Three panes:

┌──────────────┬─────────────────────────────────┬──────────────┐ │ LEFT │ CENTER │ RIGHT │ │ │ │ │ │ Block │ Live HTML preview │ Selected │ │ palette + │ (debounced 600ms after │ block's │ │ ordered │ every edit, rendered through │ properties │ │ block list │ the email-renderer sidecar) │ │ │ │ │ │ └──────────────┴─────────────────────────────────┴──────────────┘

Top bar: template name + Save button + mobile/desktop preview toggle.

Subject line: shown above the editor in its own input. Subject is a property of the template, not a block.

Available blocks

BlockWhat it does
HeadingH1 / H2 / H3 with bold styling. Use for section titles
TextParagraph — plain prose. Supports {{variable}} substitution
ImageImage with src, alt text, and width. Use absolute HTTPS URLs
ButtonCTA button with custom background colour. Set href + text
DividerHorizontal rule between sections
SpacerBlank vertical space — set height in pixels
FooterAuto-injects company name, address, and unsubscribe link. Required for compliance

Click a block in the palette to add it to the bottom of your layout. Click any block in the layout list to select it; its properties appear in the right pane. Use the up/down chevrons to reorder.

Variables

Use {{variable_name}} syntax anywhere in your subject, headings, or text.

Variables are substituted per recipient at send-time. For campaigns, the values come from contact attributes (e.g., {{first_name}} resolves to each contact’s first name). For public API sends, the values come from the variables object in your request payload.

Reserved variables

These are always available — no need to set them:

VariableValue
{{recipient_email}}The recipient’s email address
{{unsubscribe_url}}Auto-injected by the Footer block

Unknown variables

Render as empty strings rather than failing the send. This makes optional fields safe — {{coupon_code}} shows nothing for recipients without a coupon.

Live preview

The preview pane re-renders 600ms after your last edit (debounced). It calls the email-renderer  sidecar through our backend, so what you see is the actual cross-client HTML that gets shipped to recipients.

Mobile preview: click the mobile/desktop icon in the top bar to toggle. The preview pane resizes to 375px (mobile) or full-width (desktop) so you can confirm responsive behaviour.

Save + test send

Click Save to persist your template. The save also pre-compiles the final HTML so per-recipient sends don’t have to re-render — they just substitute variables into the snapshot.

Save before sending: variable substitution + sending uses the last saved version of the template. If you change a template but don’t save, the change won’t appear in sends. Click Save before testing.

To test a saved template, the easiest path is:

  1. Send a one-off campaign to a single contact (yourself)
  2. Or via API: POST /api/v1/public/email/send-template with template_id + your email

Every email must include sender identification + an unsubscribe mechanism. The Footer block handles this automatically — it renders:

{{sender_company_name}} {{sender_address}} Unsubscribe

Set the company name + mailing address in the Footer block’s properties. The unsubscribe link is auto-generated per recipient by the email-sender at send-time (HMAC-signed token).

Don’t delete the Footer block. Sending without it means your emails will fail Gmail / Yahoo’s policy checks and likely land in spam. CAN-SPAM (US), GDPR (EU), and DPDP (India) all require sender identification + a working unsubscribe path.

Editing an existing template

Click any template card in Email → Templates  to reopen the editor.

Already used in a campaign? Editing a template doesn’t change emails that have already been sent. It only affects FUTURE sends from this template. So you can safely tweak a template after a campaign launches without breaking the ones that already went out.

If you want a totally different design without losing the original, duplicate: click the template, change the name, then re-save → currently this requires copy-paste of the JSON; full duplicate-as-action button lands in a future sprint.

Deleting a template

Trash icon on the template card → confirm. Past sends keep their already-rendered HTML; future campaigns can no longer reference this template.

Best practices

  • Width: 600px for the body container is the email industry standard — most clients render this cleanly without scrollbars
  • Images: host them on a public CDN (DigitalOcean Spaces, Cloudflare R2, S3). Don’t link to your private app URLs — many email clients block authenticated image fetches
  • Alt text: always set alt on images. ~50% of inbox previews block images by default; alt text is what shows
  • Buttons: use one primary CTA per email. Multiple CTAs hurt click-through rate
  • Plain text fallback: don’t worry about it — we auto-generate a plaintext version from your blocks. Recipients on text-only mail clients see a clean version
  • Test on mobile: ~70% of marketing email opens are on mobile. Toggle to mobile preview before saving

Limits

  • Max 200 templates per account — this is generous; reach out if you need more
  • No custom CSS in this version — block properties cover ~95% of typical email styling. Sprint 6+ may add an “advanced HTML” block for power users
  • No drag-drop — reorder via the up/down arrows in the block list. Drag-drop adds 30 KB+ of JS for marginal UX gain

See also