Creating responsive, well-formatted emails that look good across all email clients is notoriously difficult. HTML email rendering varies wildly between Gmail, Outlook, Apple Mail, and dozens of other clients. MJML (Markup JavaMail Language) solves this by providing a simplified markup language that compiles to responsive, cross-client-compatible HTML.
While MJML is typically used as a CLI tool or npm package, self-hosting an MJML rendering server provides API-based template rendering for microservices, CI/CD pipelines, and multi-tenant applications. In this guide, we compare three open-source approaches to self-hosted email template rendering: MJML Server (Express), MJML-API (Symfony), and Handlebars-Mail templating.
Why Self-Host Email Template Rendering?
Third-party email template services like SendGrid’s Template Engine, Mailgun’s Templates, or Postmark’s Template API offer convenient rendering — but they lock you into specific email delivery providers, add latency to your email pipeline, and limit template customization. Self-hosting gives you:
- Provider independence — render templates locally, send through any SMTP server
- Lower latency — no network round-trip to external rendering APIs
- Custom template logic — integrate with your own data sources and templating engines
- Data privacy — template content and recipient data never leave your infrastructure
- Cost savings — no per-email or per-template rendering charges
For organizations sending transactional emails, newsletters, or notifications at scale, a self-hosted rendering layer is a valuable infrastructure component.
Tool Comparison
| Feature | MJML Server (Express) | MJML-API (Symfony) | Handlebars-Mail |
|---|---|---|---|
| GitHub Stars | 47+ | 20+ | Community pattern |
| Language | Node.js/Express | PHP/Symfony | Node.js/Handlebars |
| MJML Support | Native | Via mjml-php | Via mjml npm |
| REST API | Yes | Yes | Custom |
| Template Storage | Filesystem | Database | Filesystem |
| Multi-tenant | Manual | Built-in | Manual |
| Docker Support | Yes | Yes | Yes |
| Active Development | Stable | Stable | Community |
| License | MIT | MIT | MIT |
1. MJML Server (Express) — danihodovic/mjml-server
MJML Server is a lightweight Express.js wrapper around the MJML compiler that exposes an HTTP API for rendering email templates. Send MJML or JSON with template variables, receive compiled HTML email ready for sending.
Key Features
- Simple REST API — POST MJML markup or JSON, get rendered HTML
- Variable injection — support for Handlebars-style template variables
- Minimal dependencies — thin wrapper around the official MJML compiler
- Docker ready — easy containerization
- Stateless — no database required, perfect for horizontal scaling
Docker Compose Configuration
| |
API Usage
| |
Template File Structure
| |
When to Use
MJML Server (Express) is ideal for Node.js-based applications that need a simple, stateless email rendering microservice. Its minimal design makes it easy to deploy alongside existing services.
2. MJML-API (Symfony) — shyim/mjml-server
MJML-API is a PHP/Symfony-based REST API server for MJML rendering. It provides a more structured approach with database-backed template storage, validation, and multi-tenant support — making it suitable for SaaS platforms and agencies managing email templates for multiple clients.
Key Features
- Database-backed templates — store and version templates in a database
- Template validation — validate MJML syntax before saving
- Multi-tenant support — organize templates by organization/client
- RESTful API — full CRUD operations for templates
- Symfony ecosystem — integrates with existing Symfony applications
Docker Compose Configuration
| |
API Endpoints
| |
When to Use
MJML-API is best for PHP/Symfony applications or organizations that need structured template management with versioning, validation, and multi-tenant support.
3. Handlebars-Mail with MJML Compilation
Handlebars-Mail represents a pattern (rather than a single tool) where you combine Handlebars templating with MJML compilation in a Node.js service. This approach gives you the full power of Handlebars helpers, partials, and layouts alongside MJML’s responsive email rendering.
Key Features
- Handlebars templating — full helper system, partials, and layout support
- MJML compilation — produces responsive HTML from MJML markup
- Custom helpers — build domain-specific template helpers
- Pre-compiled templates — cache compiled templates for performance
- Flexible architecture — adapt to any application’s needs
Implementation
| |
Docker Compose Configuration
| |
Dockerfile
| |
When to Use
The Handlebars-MJML pattern is ideal for teams that need complex template logic (conditionals, loops, custom formatters) alongside responsive email rendering. It’s the most flexible approach but requires more development effort than pre-built solutions.
Email Template Architecture
| |
Template Versioning Strategy
| |
Testing Rendered Templates
| |
For related reading, see our SMTP relay comparison for self-hosted email delivery platforms, our email sieve filtering guide for server-side email processing, and our email authentication deep dive for ensuring deliverability.
FAQ
What is MJML and why should I use it?
MJML is a markup language designed specifically for creating responsive emails. Instead of writing complex nested tables and inline CSS that work across email clients, you write simple MJML tags that compile to compatible HTML. This saves hours of debugging email rendering issues.
Why self-host an MJML rendering server instead of using the CLI?
A rendering server provides a stateless API that any service in your architecture can call — frontend apps, backend services, CI/CD pipelines, or cron jobs. It centralizes template management, enables caching, and removes the need to install Node.js and MJML on every server that sends emails.
Can I use these tools with existing email templates?
Yes. All three approaches can import existing HTML email templates, though converting them to MJML markup will give you the best cross-client compatibility. MJML provides a HTML-to-MJML converter for this purpose.
How do I preview rendered emails before sending?
Most email clients support previewing HTML files directly. Save the rendered output to an .html file and open it in your browser. For accurate cross-client testing, use services like Litmus, Email on Acid, or the open-source email-client-tester project.
Can I use these tools for newsletters as well as transactional emails?
Yes. MJML supports all email types — transactional (password resets, order confirmations), marketing (newsletters, promotions), and notification emails. The template patterns are the same regardless of email type.
How do I handle template localization (i18n)?
Store language-specific templates in separate directories (e.g., templates/en/welcome.mjml, templates/de/welcome.mjml) or use Handlebars helpers to inject translated strings based on the recipient’s locale. The rendering server approach makes this easy by adding a locale parameter to the render request.
Choosing the Right Email Template Rendering Solution
- For simplicity: MJML Server (Express) provides the quickest path from zero to a working rendering API with minimal setup.
- For template management: MJML-API (Symfony) offers database-backed storage, validation, and multi-tenant features for organized template workflows.
- For maximum flexibility: The Handlebars-MJML pattern gives you full control over template logic, custom helpers, and compilation pipelines.