EmailTemplatesTemplate Engines

Template Engines

Use template engines for dynamic email content with @visulima/email

Template Engines

@visulima/email supports multiple template engines for rendering dynamic email content. All template engines implement the TemplateRenderer interface and can be used with the MailMessage.view() method.

type TemplateRenderer = (
    template: unknown,
    data?: Record<string, unknown>,
    options?: Record<string, unknown>,
) => string | Promise<string>;

Available Template Engines

Handlebars

Handlebars provides logic-less templating with support for helpers and partials.

Install: npm install handlebars

import { MailMessage } from "@visulima/email";
import { renderHandlebars } from "@visulima/email/template/handlebars";

const message = new MailMessage()
    .to("user@example.com")
    .from("sender@example.com")
    .subject("Welcome");

await message.view(renderHandlebars, "<h1>Hello {{name}}!</h1><p>Welcome to {{company}}.</p>", {
    name: "John",
    company: "Acme Corp",
});

Registering Helpers

import { registerHandlebarsHelper } from "@visulima/email/template/handlebars";

registerHandlebarsHelper("uppercase", (str: string) => str.toUpperCase());

await message.view(renderHandlebars, "<h1>Hello {{uppercase name}}!</h1>", {
    name: "John",
});

Registering Partials

import { registerHandlebarsPartial } from "@visulima/email/template/handlebars";

registerHandlebarsPartial("header", "<header><h1>{{title}}</h1></header>");

await message.view(renderHandlebars, "{{> header}}<p>Content here</p>", {
    title: "Welcome",
});

MJML

MJML is a framework that makes it easy to create responsive emails. It compiles MJML markup to HTML.

Install: npm install mjml

import { MailMessage } from "@visulima/email";
import mjml from "@visulima/email/template/mjml";

const message = new MailMessage()
    .to("user@example.com")
    .from("sender@example.com")
    .subject("Welcome");

const mjmlTemplate = `
<mjml>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text>Hello World!</mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>
`;

await message.view(mjml, mjmlTemplate);

MJML Options

OptionTypeDefaultDescription
beautifybooleanfalseBeautify the output HTML
minifybooleanfalseMinify the output HTML
keepCommentsbooleantrueKeep comments in the output
validationLevel"strict" | "soft" | "skip""soft"Validation strictness level
fontsRecord<string, string>-Custom fonts map
await message.view(mjml, mjmlTemplate, {}, {
    minify: true,
    validationLevel: "strict",
});

React Email

React Email lets you build beautiful emails using React components.

Install: npm install @react-email/render @react-email/components

import { MailMessage } from "@visulima/email";
import reactEmail from "@visulima/email/template/react-email";
import { Html, Head, Body, Text } from "@react-email/components";

const WelcomeEmail = ({ name }: { name: string }) => (
    <Html>
        <Head />
        <Body>
            <Text>Hello {name}!</Text>
        </Body>
    </Html>
);

const message = new MailMessage()
    .to("user@example.com")
    .from("sender@example.com")
    .subject("Welcome");

await message.view(reactEmail, <WelcomeEmail name="John" />);

React Email Options

OptionTypeDefaultDescription
plainTextbooleanfalseRender as plain text instead of HTML
prettybooleanfalsePretty print the output HTML

Vue Email

Vue Email lets you build emails with Vue components.

Install: npm install @vue-email/render @vue-email/components

import { MailMessage } from "@visulima/email";
import vueEmail from "@visulima/email/template/vue-email";

const message = new MailMessage()
    .to("user@example.com")
    .from("sender@example.com")
    .subject("Welcome");

await message.view(vueEmail, VueEmailComponent, {
    name: "John",
    company: "Acme",
});

Vue Email Options

OptionTypeDefaultDescription
plainTextbooleanfalseRender as plain text instead of HTML
prettybooleanfalsePretty print the output HTML
htmlToTextOptionsRecord<string, unknown>-Options for HTML-to-text conversion

HTML-to-Text

The HTML-to-text converter transforms HTML content into readable plain text. It is used automatically by MailMessage when only HTML content is provided (auto-text generation).

Install: npm install html-to-text

import htmlToText from "@visulima/email/template/html-to-text";

const text = htmlToText("<h1>Hello World</h1><p>Welcome to our platform.</p>");
// Output: "HELLO WORLD\n\nWelcome to our platform."

HTML-to-Text Options

OptionTypeDefaultDescription
wordwrapnumber | false80Word wrap limit (false to disable)
preserveNewlinesbooleanfalsePreserve newlines in output
longWordSplitobject-Options for handling long words
selectorsobject[]-Custom selectors for formatting elements

Auto-Generated Text Content

When you use message.view() or set HTML content with message.html(), @visulima/email automatically generates a plain text version using the HTML-to-text converter. This ensures email clients that don't support HTML still display readable content.

To disable auto-text generation:

await message.view(renderHandlebars, template, data, {
    autoText: false,
});

Text-Only Templates

Use viewText() for text-only template rendering:

import { renderHandlebars } from "@visulima/email/template/handlebars";

const message = new MailMessage()
    .to("user@example.com")
    .from("sender@example.com")
    .subject("Welcome");

await message.viewText(renderHandlebars, "Hello {{name}}! Welcome to {{company}}.", {
    name: "John",
    company: "Acme Corp",
});

Custom Template Engines

You can create custom template engines by implementing the TemplateRenderer type:

import type { TemplateRenderer } from "@visulima/email";

const myRenderer: TemplateRenderer = (template, data, options) => {
    let result = template as string;

    for (const [key, value] of Object.entries(data || {})) {
        result = result.replaceAll(`\${${key}}`, String(value));
    }

    return result;
};

await message.view(myRenderer, "<h1>Hello ${name}!</h1>", {
    name: "John",
});
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues