A professional, unopinionated starting point for building and managing React-based emails across your organization.
The core philosophy of this template is to decouple Email Design (Frontend) from Email Triggering (Backend). Frontend designers build and preview templates, publish a render API and type definitions, and the backend installs the generated package, posts variable data to render HTML/text, and sends emails - all independently and async. 
flowchart TD
subgraph Frontend ["Design & Development"]
A[Create/Edit Template] --> B[Live Preview]
B --> C[Deploy API & Publish Types]
end
subgraph Backend ["Triggering & Business Logic"]
D[Import Types] --> E[Call Render API with Variables]
E --> F[Send Email via SMTP/Provider]
end
C -.-> D
See how it was implemented in this repo.
You can test this immediately by visiting the Live Playground at emailtemplate.kristofajosh.dev.
- Tech Stack: Built with React, Tailwind CSS, and React Email.
- Workflow: Designers or Frontend developers create templates in
emails/, using a live preview server with hot reloading. - Output: The project exports a Render API (to generate HTML/Text) and a NPM Package containing TypeScript definitions for all templates.
- Simplicity: The backend doesn't need to know about Email content, React, Tailwind, or complex CSS inlining. It just makes a simple HTTP request.
- Type-Safety: By importing the generated types, the backend gets autocompletion and compile-time validation for email variables.
- Scalability: The rendering logic is offloaded to a dedicated service (ideally serverless), keeping the main backend lean.
- Scaffolding:
yarn gen:emailto quickly create new templates. - Live Preview: Local development environment with hot reloading via React Email.
- Type-Safe: Automatically generates TypeScript definitions for all templates.
- API Ready: Built-in Express server to render emails to HTML/Text on the fly.
- Tailwind CSS: Pre-configured for modern styling.
- CI/CD Ready: Workflows for automated versioning, publishing, and deployment.
Clone this template and run the following command to rename the package scope to your organization:
yarn rename-scope @your-orgThis will update package.json, README.md, and other relevant files.
Then, update the repository field in package.json to your GitHub URL.
Copy .env.sample to .env and adjust as needed:
cp .env.sample .envPORT: (Optional) Port for the API server (default 8080).BASE_URL: The URL of your frontend application.BASE_ASSET_URL: The URL where your email assets/images are hosted.
Create a new email template:
yarn gen:emailThis scaffolds a new .tsx file in emails/ using Plop. You can configure this to suite your needs.
Preview emails:
yarn devOpen http://localhost:3000 to see the live preview.
- API: Deploy the
Dockerfileto your preferred host. Serverless environments (like Google Cloud Run or AWS Fargate) are highly recommended for cost-efficiency and automatic scaling. - Types: With step 1 setup correctly, Auto publishes the package to a private registry (GitHub Packages, NPM) so your backend can consume the generated types.
Check
.github/workflowsfor pre-configured GitHub Actions.
Install your private package:
npm install @your-org/email-templatesinstallation in the backend may require .npmrc file
registry=https://registry.npmjs.org/
@your-org:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
Use the types to call the API with full type-safety:
import { EmailRenderPayload } from '@your-org/email-templates';
// TypeScript will enforce correct variables based on the template!
const payload: EmailRenderPayload<'general', 'christmas'> = {
emailModule: 'general',
template: 'christmas',
variables: {
email: 'recipient@example.com',
name: 'John Doe',
}
};
const response = await fetch('https://your-email-api.com/api/render', {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' }
});
const { html, text } = await response.json();POST /api/render: Returns JSON{ html: string, text: string }.POST /api/render/html: Returns raw HTML body.POST /api/render/text: Returns plain text body.
yarn dev: Start the preview server.yarn dev:api: Start the API server locally.yarn gen:email: Scaffold a new email.yarn gen:templates: Re-generate the template index and types.yarn build:api: Build the production API.yarn build:types: Build the TypeScript definitions.yarn rename-scope @your-org: Rename the package scope across the project.
This project is licensed under the MIT License - see the LICENSE file for details.
If this project helped you, please consider giving it a star!