---
name: email-dev
description: Email template development with React Email and Tailwind CSS. Use when creating or modifying email templates, testing email rendering, or building email HTML from React components.
---
# Email Template Development
This skill guides the development of email templates using React Email with Tailwind CSS.
## When to use this skill
- Creating new email templates
- Modifying existing email templates
- Testing email rendering in different clients
- Debugging email template styling
- Compiling React Email to production HTML
## Quick Commands
```bash
make dev-emails # Start React Email dev server (http://localhost:3001)
make build-emails # Compile React Email to HTML with Jinja2 variables
```
## Development Workflow
### 1. Start Development Server
```bash
make dev-emails
```
Opens React Email preview UI at http://localhost:3001:
- Live preview of all templates
- Mobile/desktop view toggle
- Built-in Tailwind CSS support
- Auto-reload on changes
### 2. Create or Edit Templates
Templates location: `backend/emails/templates/`
**Shared Components:**
- `_BaseLayout.tsx`: Main email layout wrapper with Tailwind support
- `_Button.tsx`: Styled button component
**Example Template:**
```tsx
import { Button, Html, Text, Tailwind } from '@react-email/components';
import { BaseLayout } from './_BaseLayout';
interface WelcomeEmailProps {
userName: string;
loginUrl: string;
}
export const WelcomeEmail = ({ userName, loginUrl }: WelcomeEmailProps) => (
Hello {userName}!
Thanks for joining Arive. Get started by logging in:
);
WelcomeEmail.PreviewProps = {
userName: "John Doe",
loginUrl: "https://app.tryarive.com/login",
} as WelcomeEmailProps;
export default WelcomeEmail;
```
### 3. Use Tailwind CSS Classes
The email templates support Tailwind CSS, which gets compiled to inline styles:
```tsx
Confirm
```
### 5. Register Template Variables
Edit `backend/emails/scripts/build.ts`:
```typescript
const TEMPLATE_VARIABLES: Record> = {
'WelcomeEmail': {
userName: 'John Doe',
loginUrl: 'https://app.tryarive.com/login',
},
'MyNewEmail': {
userName: 'Test User',
confirmUrl: 'https://app.tryarive.com/confirm/abc123',
},
};
```
### 6. Build Production Templates
```bash
make build-emails
```
This compiles:
- React Email components → HTML
- Tailwind CSS classes → inline styles
- Props → Jinja2 variables
- Output: `backend/templates/emails-react/*.html.jinja2`
### 7. Use Template in Backend
Add method to `EmailService` in `backend/app/lib/email.py`:
```python
async def send_welcome_email(
self,
to_email: str,
user_name: str,
login_url: str,
) -> None:
"""Send welcome email to new user."""
await self._send_email(
template_name="WelcomeEmail.html.jinja2",
to_email=to_email,
subject="Welcome to Arive!",
template_vars={
"userName": user_name,
"loginUrl": login_url,
},
)
```
Call from route handler:
```python
@post("/register")
async def register_user(
data: RegisterRequest,
email_service: EmailService,
) -> UserResponse:
user = await create_user(data)
await email_service.send_welcome_email(
to_email=user.email,
user_name=user.name,
login_url=f"https://app.tryarive.com/login",
)
return user
```
## Template Structure
```
backend/emails/
├── templates/ # React Email source (.tsx)
│ ├── _BaseLayout.tsx # Shared layout component
│ ├── _Button.tsx # Shared button component
│ ├── WelcomeEmail.tsx # Example template
│ └── MyEmail.tsx # Your new template
├── scripts/
│ ├── build.ts # Build script (React → HTML)
│ └── watch.ts # Dev server script
├── tailwind.config.ts # Tailwind CSS config
└── package.json # npm dependencies
backend/templates/emails-react/ # Compiled output (generated)
├── WelcomeEmail.html.jinja2
└── MyEmail.html.jinja2
```
## Design System Guidelines
### Colors
Use semantic color names that match the frontend:
- **Foreground**: Main text color (`text-foreground`)
- **Muted**: Secondary text (`text-muted-foreground`)
- **Primary**: Brand color for CTAs (`bg-primary`)
- **Neutral grays**: Backgrounds and borders (`bg-neutral-50`, `border-neutral-200`)
### Typography
```tsx
HeadingBody textCaption
```
### Spacing
```tsx
{/* Padding */}
{/* Margin bottom */}
{/* Vertical spacing between children */}
```
### Layout
```tsx
{/* Max width container */}
{/* Content */}
```
## Testing Email Rendering
### 1. Preview in Dev Server
- Check desktop and mobile views
- Test all interactive elements
- Verify spacing and alignment
### 2. Send Test Emails
```python
# In backend shell or test script
from app.lib.email import EmailService
email_service = EmailService()
await email_service.send_welcome_email(
to_email="your-email@example.com",
user_name="Test User",
login_url="https://app.tryarive.com/login",
)
```
### 3. Email Client Testing
Test in multiple email clients:
- Gmail (web + mobile app)
- Outlook (web + desktop)
- Apple Mail (macOS + iOS)
- Others as needed
## Common Issues
### Styles not applying
- **Tailwind not compiling**: Run `make build-emails`
- **Inline styles missing**: Check Tailwind config includes all classes
- **Email client stripping styles**: Use supported CSS properties only
### Variables not rendering
- **Jinja2 syntax errors**: Check template output in `backend/templates/emails-react/`
- **Missing variables**: Verify TEMPLATE_VARIABLES in `build.ts`
- **Type mismatches**: Ensure props match template variables
### Images not loading
- **Relative paths**: Use absolute URLs for images
- **CORS issues**: Ensure image hosting allows email embedding
- **Size**: Optimize images for email (< 100KB recommended)
## Best Practices
1. **Mobile-first**: Design for mobile screens, test responsive behavior
2. **Inline styles**: Tailwind automatically inlines, but verify after build
3. **Alt text**: Always include alt text for images
4. **Preheader text**: Set via `previewText` prop in BaseLayout
5. **CTA buttons**: Make them prominent and tap-friendly (44px min height)
6. **Dark mode**: Consider email client dark mode support
7. **Accessibility**: Use semantic HTML and proper color contrast
## Production Deployment
Before deploying:
1. Run `make build-emails` to compile templates
2. Commit compiled templates in `backend/templates/emails-react/`
3. Templates are included in Docker image build
4. No Node.js runtime needed in production
Backend serves templates via Litestar's JinjaTemplateEngine at runtime.