| docs | ||
| public | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .env.test | ||
| .gitignore | ||
| CHANGELOG.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.js | ||
| index.html | ||
| jest.config.cjs | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.cjs | ||
| README.md | ||
| server.ts | ||
| tailwind.config.cjs | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
Email Template Service
Production-ready email template service with beautiful React templates and secure backend API.
✨ Features
📧 Email Templates
- Event Invitations - Event invitations with RSVP functionality
- Team Invitations - Team member invitations with branded styling and acceptance links
- Payment Requests - Basic payment requests with payment buttons or bank transfer details
- Enhanced Payment Requests - Detailed payment requests with itemized line items and automatic status updates
- Invoice Sharing - Secure invoice sharing with expiration and access limits
- Password Reset - Secure password recovery emails
- Invoices - Professional proforma invoices
- Tax Reports - VAT and withholding tax reports
- Newsletters - Marketing and announcement emails
🛡️ Production Ready
- Security: Input validation, rate limiting, CORS protection
- Monitoring: Health checks, structured logging, error tracking
- Performance: Optimized templates, request caching
- Reliability: Comprehensive error handling, graceful shutdown
🎨 Developer Experience
- Visual Designer: React-based template editor
- Type Safety: Full TypeScript coverage
- Hot Reload: Development server with instant updates
- Docker Support: One-command deployment
🚀 Quick Start
1. Installation
git clone <repository>
cd email-template-service
npm install
2. Environment Setup
cp .env.example .env
# Edit .env with your Resend API key and domain
3. Development
# Start template designer (frontend)
npm run dev
# Start API server (backend) - separate terminal
npm run server:dev
4. Production
# Docker (recommended)
docker-compose up -d
# Or Node.js
npm run build && npm start
📡 API Usage (For Yaltopia Backend)
Send Invitation Email
// From your Yaltopia backend when user registers for event
const invitationData = {
to: user.email,
eventName: event.name,
dateTime: "March 25, 2026 at 2:00 PM",
location: event.location,
ctaUrl: `https://yaltopia.com/events/${event.id}/rsvp`,
company: {
name: "Yaltopia Ticket",
logoUrl: "https://yaltopia.com/logo.png"
}
}
const response = await fetch('http://email-service:3001/api/emails/invitation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invitationData)
})
Send Team Invitation
// From your Yaltopia backend when inviting team members
const teamInvitationData = {
to: user.email,
recipientName: user.name,
inviterName: inviter.name,
teamName: team.name,
invitationLink: `https://yaltopia.com/teams/join?token=${invitationToken}`,
customMessage: "Join our team and let's build something amazing!",
company: {
name: "Yaltopia Ticket",
logoUrl: "https://yaltopia.com/logo.png",
primaryColor: "#10b981"
}
}
const response = await fetch('http://email-service:3001/api/emails/team-invitation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(teamInvitationData)
})
Send Enhanced Payment Request
// From your Yaltopia backend for detailed payment requests
const enhancedPaymentData = {
to: customer.email,
recipientName: customer.name,
paymentRequestNumber: "PR-2026-001",
amount: 2500.00,
currency: "USD",
description: "Monthly subscription and services",
dueDate: "March 31, 2026",
lineItems: [
{
description: "Yaltopia Pro Subscription",
quantity: 1,
unitPrice: 199.00,
total: 199.00
},
{
description: "Setup and Configuration",
quantity: 5,
unitPrice: 150.00,
total: 750.00
}
],
notes: "Payment is due within 30 days.",
company: {
name: "Yaltopia Ticket",
bankDetails: {
bankName: "Your Bank",
accountName: "Yaltopia Ticket Ltd",
accountNumber: "123456789",
referenceNote: "Payment for PR-2026-001"
}
}
}
const response = await fetch('http://email-service:3001/api/emails/enhanced-payment-request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(enhancedPaymentData)
})
Send Invoice Share
// From your Yaltopia backend for invoice sharing
const invoiceShareData = {
to: recipient.email,
recipientName: recipient.name,
senderName: sender.name,
invoiceNumber: invoice.number,
customerName: invoice.customer.name,
amount: invoice.totalAmount,
currency: "USD",
status: "SENT", // 'DRAFT', 'SENT', 'PAID', 'OVERDUE', 'CANCELLED'
shareLink: `https://yaltopia.com/invoices/shared/${shareToken}`,
expirationDate: "March 31, 2026",
accessLimit: 5,
customMessage: "Please review this invoice.",
company: {
name: "Yaltopia Ticket",
logoUrl: "https://yaltopia.com/logo.png"
}
}
const response = await fetch('http://email-service:3001/api/emails/invoice-share', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invoiceShareData)
})
Send Password Reset
// From your Yaltopia backend for password reset
const resetData = {
to: user.email,
resetLink: `https://yaltopia.com/reset-password?token=${resetToken}`,
recipientName: user.firstName,
company: {
name: "Yaltopia Ticket"
}
}
const response = await fetch('http://email-service:3001/api/emails/password-reset', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(resetData)
})
🏗️ Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Yaltopia │ │ Email Service │ │ Resend │
│ Backend │───▶│ (Express.js) │───▶│ Email API │
│ (with data) │ │ + Templates │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
Has Event Data Renders Templates Email Delivery
Simple & Efficient: Yaltopia backend calls this service with data, service renders beautiful templates and sends emails via Resend.
📁 Project Structure
├── src/
│ ├── components/ # React UI components
│ ├── templates/ # Email template components
│ ├── lib/ # Utilities and services
│ │ ├── config.ts # Environment configuration
│ │ ├── logger.ts # Structured logging
│ │ ├── validation.ts # Input validation schemas
│ │ └── resendService.ts # Email service
│ └── ...
├── docs/ # Documentation
├── server.ts # Production API server
├── docker-compose.yml # Docker configuration
└── .env.example # Environment template
🔧 Configuration
Required Environment Variables
RESEND_API_KEY=re_your_api_key_here
FROM_DOMAIN=yaltopia.com
Optional Configuration
FROM_EMAIL=noreply@yaltopia.com
NODE_ENV=production
PORT=3001
RATE_LIMIT_MAX=20
RATE_LIMIT_WINDOW_MS=900000
CORS_ORIGIN=https://yaltopia.com
LOG_LEVEL=info
🛡️ Security Features
- Input Validation: Zod schemas for all API inputs
- Rate Limiting: Configurable email sending limits (default: 10/15min)
- Security Headers: Helmet.js with CSP, HSTS, XSS protection
- CORS Protection: Configurable origin restrictions
- Privacy Protection: Email/IP masking in logs
- Error Handling: No sensitive data in error responses
📊 Monitoring
Health Check
curl http://localhost:3001/health
# Returns: {"status": "healthy", "timestamp": "..."}
Structured Logging
{
"level": "info",
"message": "Email sent successfully",
"timestamp": "2026-03-12T10:00:00.000Z",
"meta": {
"templateId": "invitation",
"to": "u***@example.com",
"messageId": "abc123"
}
}
📚 Documentation
- API Reference - Complete API documentation with examples
- Deployment Guide - Production deployment instructions
- Security Guide - Security features and best practices
🚀 Deployment Options
Docker (Recommended)
docker-compose up -d
Cloud Platforms
- Vercel:
vercel --prod - Railway:
railway up - Heroku:
git push heroku main - AWS/GCP: Standard Node.js deployment
Manual Node.js
npm run build
npm start
🧪 Development Scripts
npm run dev # Start frontend development
npm run server:dev # Start backend with hot reload
npm run build # Build for production
npm run type-check # Validate TypeScript
npm run lint # Run ESLint
npm run validate # Full validation (lint + build)
npm start # Start production server
🔍 Troubleshooting
Common Issues
"Domain not verified"
- Verify your domain in Resend dashboard
- Add SPF record:
v=spf1 include:_spf.resend.com ~all
"Rate limit exceeded"
- Check current limits:
curl http://localhost:3001/api - Adjust
RATE_LIMIT_MAXin environment variables
"Email not delivered"
- Check Resend logs in dashboard
- Verify recipient email address
- Check spam folder
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
npm run validate - Submit a pull request
📄 License
Private - Internal use only
Ready for production with enterprise-grade security and reliability! 🚀
For detailed documentation, see the docs folder.