Wraps Logo
Templates Quickstart

Get Started with Templates

Build email templates as React components, preview them with hot-reload, and push to AWS SES — all from your codebase.

What you'll build

  • A templates-as-code project with React Email components
  • Hot-reload local preview for rapid iteration
  • Templates pushed to AWS SES and ready to send

Time: ~5 minutes

Prerequisites

Before you begin, make sure you have:

  • Node.js 20 or later installed
  • Email infrastructure deployed via wraps email init (see the Email Quickstart)
  • A Wraps account with an organization (wraps auth login)

1
Initialize Templates

Run the scaffold command from your project root to create the templates directory:

GNU Bashterminal.sh
npx @wraps.dev/cli email templates init

This creates the following structure in your project:

Project Structure
wraps/├── wraps.config.ts          # Project configuration├── templates/│   └── welcome.tsx          # Example template├── brand.ts                 # Brand kit (colors, fonts, logo)└── _components/             # Shared components

What gets scaffolded?

  • wraps.config.ts — project config (org, sender address, template directory)
  • brand.ts — shared brand kit for colors, fonts, and logos
  • templates/welcome.tsx — a working example template

2
Write a Template

Templates are React components built with React Email. Each file exports the component as default, plus metadata for the subject line, email type, and preview text. Here is the scaffolded example:

Reactwraps/templates/welcome.tsx
import {  Body,  Container,  Head,  Heading,  Html,  Preview,  Section,  Text,} from '@react-email/components';import { Footer } from './_components/footer';export const subject = 'Welcome to {{companyName}}, {{firstName}}!';export const emailType = 'transactional' as const;export const previewText = "We're glad to have you on board.";export const testData = {  firstName: 'Jane',  companyName: 'Acme',  unsubscribeUrl: 'https://example.com/unsubscribe',};interface Props {  firstName: string;  companyName: string;  unsubscribeUrl: string;}export default function WelcomeEmail({  firstName,  companyName,  unsubscribeUrl,}: Props) {  return (    <Html>      <Head />      <Preview>{previewText}</Preview>      <Body style={{ backgroundColor: '#f6f9fc', fontFamily: 'system-ui, sans-serif' }}>        <Container style={{ margin: '0 auto', padding: '40px 0', maxWidth: '580px' }}>          <Section style={{ backgroundColor: '#fff', borderRadius: '8px', padding: '40px' }}>            <Heading style={{ fontSize: '24px', color: '#1f2937' }}>              Welcome, {firstName}!            </Heading>            <Text style={{ fontSize: '16px', color: '#4b5563', lineHeight: '1.6' }}>              Thanks for signing up for {companyName}. We're excited to have you on board.            </Text>          </Section>          <Footer unsubscribeUrl={unsubscribeUrl} />        </Container>      </Body>    </Html>  );}

Variable interpolation

Use {{variableName}} syntax in the subject export. These are replaced with values from templateData at send time.

3
Preview Locally

Start the local preview server to see your templates rendered in the browser with hot-reload:

GNU Bashterminal.sh
npx @wraps.dev/cli email templates preview# Opens http://localhost:3333 with hot-reload

The preview server watches for file changes and reloads automatically. Test data from the testData export is used to populate the template in the preview UI.

4
Push to Production

Push your templates to both AWS SES and the Wraps dashboard. Only modified templates are pushed by default:

GNU Bashterminal.sh
npx @wraps.dev/cli email templates push

Useful flags

  • --template welcome — push a single template
  • --dry-run — see what would change without pushing
  • --force — re-push all templates regardless of changes

5
Send Using the Template

Once pushed, send emails using the template name and pass dynamic data via the SDK:

TypeScriptsend.ts
import { WrapsEmail } from '@wraps.dev/email';const email = new WrapsEmail();// Sending via the SDK calls SES directly from your AWS account.// You provide the unsubscribe URL — it points at an endpoint you own.// See "Unsubscribe handling" below for the platform-managed alternative.await email.sendTemplate({  from: 'hello@yourdomain.com',  to: 'user@example.com',  template: 'welcome',  templateData: {    firstName: 'Alice',    companyName: 'Acme',    unsubscribeUrl: 'https://yourdomain.com/unsubscribe?token=abc123',  },});

Template data is merged at send time. Variable placeholders in the subject line (like {{firstName}}) are also replaced automatically.

Unsubscribe handling

Every variable accessed on the template's props (including unsubscribeUrl) is compiled into a {{unsubscribeUrl}} placeholder in the template pushed to SES. What fills that placeholder at send time depends on how you send:

SDK (your SES)

@wraps.dev/email calls SES directly from your AWS account. Wraps is not in the path.

  • You pass unsubscribeUrl in templateData— it points at an endpoint you own.
  • You run the unsubscribe handler and maintain your own suppression list (or use email.suppression).
  • No List-Unsubscribe headers are added for you — add them with the headers option if you need RFC 8058 one-click unsubscribe.
Platform broadcasts

When the send goes through a Wraps broadcast or workflow step, Wraps handles unsubscribe end-to-end.

  • Wraps generates a signed, per-recipient URL and substitutes {{unsubscribeUrl}} at send time.
  • Clicks land on the hosted unsubscribe page, suppress the contact, and emit a workflow event — no endpoint to build.
  • Requires export const emailType = 'marketing' as const; on the template. That flag also enables RFC 8058 List-Unsubscribe and List-Unsubscribe-Post headers for Gmail/Apple Mail one-click unsubscribe.
  • {{preferencesUrl}} is available alongside {{unsubscribeUrl}} if you prefer a preferences page over a hard unsubscribe.

The template file itself is the same for both paths. Mark marketing templates with the emailType flag and reference the placeholder:

Reactwraps/templates/newsletter.tsx
export const emailType = 'marketing' as const;// In any marketing template, reference the Wraps-managed placeholder.// When sent via a broadcast or workflow, Wraps generates a signed,// per-recipient URL and substitutes it at send time.<Footer unsubscribeUrl={unsubscribeUrl} />// {{preferencesUrl}} is also auto-injected if you want a// "manage preferences" link instead of a hard unsubscribe.

Next Steps

Templates Guide

Configuration, brand kits, change detection, and advanced template patterns.

Full Guide
Email SDK Reference

All available methods for sending emails and managing templates programmatically.

View SDK Docs

Need Help?

If you run into any issues, check our GitHub discussions or open an issue.

Get Help