Template Management (MJML & Handlebars)
NexoMailer provides a unified engine to manage your email layouts. It handles the heavy lifting of compiling MJML (Responsive HTML for Emails), injecting dynamic data via Handlebars, and caching the results for high-performance delivery.
Installation
Install the Templates module:
npm install @nexomailer/templates(Alternatively, you can use pnpm add @nexomailer/templates or yarn add @nexomailer/templates).
1. Professional Workflow
Global Branding
Avoid repeating your company logo or social links in every single template. You can set them once globally, and they will automatically be available as variables ({{logo}}) in all your templates.
import { NexoMailer } from '@nexomailer/core';
import { TemplateEngine } from '@nexomailer/templates';
const mailer = new NexoMailer({ /* config */ });
// Access the templates engine
const templates = new TemplateEngine();
// Define data that should exist in every email you send
templates.setGlobalData({
logo: 'https://cdn.yoursite.com/logo.png',
companyName: 'NexoDev Inc.',
website: 'https://nexodev.com'
});Loading from Directory
For production, keep your templates organized in a folder structure instead of hardcoding them. Each folder should contain a template.mjml (or .hbs).
// Point NexoMailer to your templates folder
// It will scan all subdirectories and register them using the folder name
await mailer.templates.loadDirectory('./src/emails');
// If you have a folder named 'invoice', you can now send it like this:
await mailer.send({
to: 'client@example.com',
subject: 'Your Invoice',
template: {
name: 'invoice', // Matches folder name
data: { amount: '$50.00' }
}
});2. Built-in Template Gallery
NexoMailer comes with a library of minimalist, professional templates that work right out of the box without you writing any HTML.
// Load all default templates provided by the SDK
await mailer.templates.loadBuiltIn();otp (One-Time Password)
Ideal for 2FA, password resets, or registration verification.
- Required Data:
code,expiresIn - Example Usage:
await mailer.send({
to: 'user@example.com',
subject: 'Your Login Code',
template: {
name: 'otp',
data: { code: '448822', expiresIn: 10 } // Automatically injected into the HTML
}
});welcome (Welcome Email)
A clean, friendly outreach for new signups.
- Required Data:
name,companyName,actionUrl - Example Usage:
await mailer.send({
to: 'user@example.com',
subject: 'Welcome to NexoDev!',
template: {
name: 'welcome',
data: { name: 'Ankit', companyName: 'NexoDev', actionUrl: 'https://app.nexodev.com' }
}
});reset-password
A focused, urgent template for security actions.
- Required Data:
name,resetUrl - Example Usage:
await mailer.send({
to: 'user@example.com',
subject: 'Reset your password',
template: {
name: 'reset-password',
data: { name: 'Ankit', resetUrl: 'https://app.nexodev.com/reset?token=xyz' }
}
});3. Advanced Customization
Conditional Logic
Since NexoMailer uses Handlebars behind the scenes, you can add dynamic logic inside your MJML files without breaking the layout.
<mj-section>
<mj-column>
<!-- Handlebars IF statement -->
{{#if isPremium}}
<mj-text>Thank you for being a Pro member!</mj-text>
{{else}}
<mj-button href="/upgrade">Upgrade Now</mj-button>
{{/if}}
</mj-column>
</mj-section>Custom Helpers
You can register your own Handlebars helpers to process data right before rendering:
import Handlebars from 'handlebars';
// Create a custom formatting helper
Handlebars.registerHelper('uppercase', (str) => {
if (typeof str === 'string') return str.toUpperCase();
return str;
});
// Now use {{uppercase companyName}} inside your MJML templates!Performance & Validation
[!TIP] Pre-compilation: Every template is compiled from MJML to HTML and cached in memory during registration (e.g. when you call
loadDirectory). This ensures sub-millisecond rendering times even under high load.
[!WARNING] MJML Tags: NexoMailer supports all standard MJML tags. However, avoid using illegal CSS attributes (like
margin-toponmj-section) inside standard HTML tags, as it may break cross-client compatibility.