---
title: "Use MJML to build email layouts · Agent Wranglers"
url: https://agentwranglers.se/playbook/stack/product-services/mjml-email
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Use MJML to build email layouts

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/stack/rules.json) holds every rule of this playbook as JSON.

- Level: Recommended
- Chapter: [Product services](https://agentwranglers.se/playbook/stack/product-services)
- Rule: Write each email layout in MJML, compile it to HTML in the build with strict validation, and fill in the values with your template engine.
- Applies when: The project it sends email.
- Cost: Open source. MIT licence, free to use in any project.
- How: MJML 1.0.0 shipped on 29 January 2016, and 5.4.1 on 10 September 2026. npm counted about 1.1 million downloads in the week to 18 October 2026. Its engine turns short tags into the responsive HTML that email clients need, so nobody writes layout tables by hand. Compile it with Node.js or its command line, then render the output with any template engine. The output still needs what [Build layout that Outlook can show](https://agentwranglers.se/playbook/email/layout-and-accessibility/layout-tables) asks, so test it in the clients. Choose something else when your email templates are React components. React Email's components package reached 1.0.0 in November 2025, so record the exception.
- Check: The build compiles every `.mjml` file with `validationLevel: 'strict'` and fails on any error. No sent template is hand-written HTML.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import { readFile, writeFile } from 'node:fs/promises';
import mjml2html from 'mjml';

export async function compileTemplate(name) {
  const source = await readFile(`emails/${name}.mjml`, 'utf8');
  const { html } = await mjml2html(source, { validationLevel: 'strict' });
  await writeFile(`build/emails/${name}.html`, html);
}
```

### Python example

```python
from jinja2 import Environment, FileSystemLoader, select_autoescape

emails = Environment(loader=FileSystemLoader("build/emails"), autoescape=select_autoescape(["html"]))

def render_receipt(order) -> str:
    return emails.get_template("receipt.html").render(order=order)
```

## Sources

- [MJML documentation](https://documentation.mjml.io/)

## Related rules

- [Build layout that Outlook can show](https://agentwranglers.se/playbook/email/layout-and-accessibility/layout-tables) in Email

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/stack/product-services/mjml-email">Agent Wranglers software choices playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Use Better Auth or django-allauth for sign-in inside the app](https://agentwranglers.se/playbook/stack/product-services/sign-in-library)
- Next: [Use Playwright or WeasyPrint to turn HTML into PDF](https://agentwranglers.se/playbook/stack/product-services/html-to-pdf)
- [Product services](https://agentwranglers.se/playbook/stack/product-services)
