Templates Engine

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-top on mj-section) inside standard HTML tags, as it may break cross-client compatibility.