Email Template Development
This guide explains how to create and customize email templates in TestPlanIt using the Handlebars templating system.
Overview
TestPlanIt uses Handlebars for email templating, providing:
- Separation of content and presentation
- Reusable layouts and partials
- Template helpers for common operations
- Responsive, professional email designs
Template Structure
Directory Layout
lib/email/
├── template-service.ts # Template rendering engine
├── notificationTemplates.ts # Email sending functions
├── templates/
│ ├── layouts/ # Base layouts
│ │ └── main.hbs # Default layout
│ ├── partials/ # Reusable components
│ │ └── header.hbs # Logo header
│ ├── notification.hbs # Single notification
│ └── daily-digest.hbs # Daily summary
Template Hierarchy
- Layout - Base HTML structure (header, footer, styles)
- Template - Specific email content
- Partials - Reusable components
Creating Email Templates
Basic Template
Create a new file in lib/email/templates/:
Using the Template
import { renderEmailTemplate } from './lib/email/template-service';
// Render the template
const { html, subject } = await renderEmailTemplate('welcome', {
userName: 'John Doe',
appUrl: process.env.NEXTAUTH_URL,
subject: 'Welcome to TestPlanIt!'
});
// Send the email
await transporter.sendMail({
from: process.env.EMAIL_FROM,
to: user.email,
subject,
html
});
Available Helpers
Date Formatting
Comparisons
Available Operators
eq- Equal tone- Not equal togt- Greater thangte- Greater than or equallt- Less thanlte- Less than or equal
Template Variables
Common Variables
All templates receive these variables:
{
appUrl: string; // Application URL
userId: string; // Current user ID
currentYear: number; // For copyright
userName?: string; // User's display name
subject: string; // Email subject
}
Custom Variables
Pass additional data as needed:
await renderEmailTemplate('custom-template', {
// Common variables
...commonData,
// Custom variables
projectName: 'My Project',
testResults: {
passed: 95,
failed: 5,
total: 100
}
});
Layouts
Default Layout
The main.hbs layout provides:
- Responsive design
- Consistent header/footer
- Base styles
- Unsubscribe links
Custom Layouts
Create new layouts in templates/layouts/:
Use custom layout:
await renderEmailTemplate('alert', data, {
layout: 'minimal'
});
Partials
Creating Partials
Add files to templates/partials/:
Using Partials
Styling Emails
Inline Styles
Email clients require inline styles:
CSS Classes
Define classes in the layout:
Responsive Design
Use media queries for mobile:
Testing Templates
Local Development
-
Set up MailHog for local email testing:
docker run -p 1025:1025 -p 8025:8025 mailhog/mailhog -
Configure
.env:EMAIL_SERVER_HOST=localhost
EMAIL_SERVER_PORT=1025
EMAIL_SERVER_USER=
EMAIL_SERVER_PASSWORD= -
View emails at http://localhost:8025
Preview Templates
Create a preview script:
// scripts/preview-email.ts
import { renderEmailTemplate } from '../lib/email/template-service';
async function preview() {
const { html } = await renderEmailTemplate('notification', {
userName: 'Test User',
notification: {
title: 'Test Notification',
message: 'This is a test',
createdAt: new Date()
},
appUrl: 'http://localhost:3000'
});
console.log(html);
}
preview();
Best Practices
Content
- Keep subject lines under 50 characters
- Use preheader text effectively
- Include alt text for images
- Provide text-only alternatives
Design
- Use tables for layout (better email client support)
- Stick to web-safe fonts
- Test with images disabled
- Keep width under 600px
Development
- Test across email clients (Gmail, Outlook, Apple Mail)
- Validate HTML markup
- Minimize external dependencies
- Use absolute URLs for links and images
Security
- Sanitize user input
- Don't include sensitive data
- Use HTTPS URLs
- Include unsubscribe links
Common Patterns
Notification List
Conditional Content
Call-to-Action Buttons
Troubleshooting
Template Not Found
- Ensure file exists in
templates/directory - Check file extension is
.hbs - Verify template name in code matches filename
Variables Not Rendering
- Check variable names match exactly
- Ensure data is passed to template
- Use
{{{variable}}}for HTML content
Styles Not Working
- Use inline styles for better support
- Test in target email clients
- Avoid advanced CSS features
Email Not Sending
- Verify SMTP configuration
- Check email worker is running
- Review logs for errors
- Test with simple template first