Skip to main content

Quick Start

Minimal Example

Render MJML to HTML in a single line:

import dev.jcputney.mjml.MjmlRenderer;
import dev.jcputney.mjml.MjmlRenderResult;

MjmlRenderResult result = MjmlRenderer.render("<mjml><mj-body></mj-body></mjml>");
String html = result.html();

All render() overloads return an MjmlRenderResult record containing the rendered HTML, document title, and preview text.

Working Example

Here is a complete example that renders an email with a heading and a text block:

import dev.jcputney.mjml.MjmlRenderer;
import dev.jcputney.mjml.MjmlRenderResult;

public class EmailExample {
public static void main(String[] args) {
String mjml = """
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="24px" font-weight="bold">
Welcome!
</mj-text>
<mj-text>
This email was rendered with mjml-java.
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
""";

MjmlRenderResult result = MjmlRenderer.render(mjml);
System.out.println(result.html());
}
}

Using Configuration

For more control over rendering, pass an MjmlConfiguration object to get back an MjmlRenderResult:

import dev.jcputney.mjml.MjmlRenderer;
import dev.jcputney.mjml.MjmlConfiguration;
import dev.jcputney.mjml.MjmlRenderResult;

MjmlConfiguration config = MjmlConfiguration.builder()
.language("en")
.build();

MjmlRenderResult result = MjmlRenderer.render(mjml, config);

String html = result.html(); // The rendered HTML
String title = result.title(); // Title from <mj-title>, or empty string

MjmlRenderResult is a Java record with three accessors:

MethodReturn TypeDescription
html()StringThe fully rendered HTML string
title()StringThe document title extracted from <mj-title>, or an empty string if none was set
previewText()StringThe preview text extracted from <mj-preview>, or an empty string if none was set

Rendering a File

You can render an MJML file directly from a Path. A FileSystemIncludeResolver is automatically configured using the file's parent directory:

import dev.jcputney.mjml.MjmlRenderer;
import dev.jcputney.mjml.MjmlRenderResult;
import java.nio.file.Path;

MjmlRenderResult result = MjmlRenderer.render(Path.of("/templates/email.mjml"));
String html = result.html();

You can also pass a configuration. If no IncludeResolver is set, one is auto-created from the file's parent directory:

MjmlConfiguration config = MjmlConfiguration.builder()
.language("en")
.build();

MjmlRenderResult result = MjmlRenderer.render(Path.of("/templates/email.mjml"), config);

Using mj-include

To render templates that use <mj-include> to reference external files, configure an IncludeResolver:

import dev.jcputney.mjml.MjmlRenderer;
import dev.jcputney.mjml.MjmlConfiguration;
import dev.jcputney.mjml.FileSystemIncludeResolver;
import java.nio.file.Path;

MjmlConfiguration config = MjmlConfiguration.builder()
.includeResolver(new FileSystemIncludeResolver(Path.of("/path/to/templates")))
.build();

String mjml = """
<mjml>
<mj-body>
<mj-include path="header.mjml" />
<mj-section>
<mj-column>
<mj-text>Body content</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
""";

MjmlRenderResult result = MjmlRenderer.render(mjml, config);

FileSystemIncludeResolver resolves include paths relative to the given base directory and prevents path traversal outside of it.

Error Handling

All rendering errors throw MjmlException (unchecked):

import dev.jcputney.mjml.MjmlException;

try {
MjmlRenderResult result = MjmlRenderer.render(mjmlString);
} catch (MjmlException e) {
System.err.println("Failed to render MJML: " + e.getMessage());
}

Thread Safety

The MjmlRenderer.render() methods are thread-safe. Each call creates its own render pipeline and context, so concurrent calls do not share mutable state. MjmlConfiguration instances are immutable and safe to share across threads.