by Midori

MJML is a semantic markup language and open-source engine that compiles responsive email templates into cross-client HTML. Designed for developers building production email workflows.
This block provides the full MJML monorepo source: a markup-language compiler that transforms MJML templates into responsive HTML email. It includes the core engine, every standard component (body, button, carousel, accordion, section, image, text, etc.), the XML parser, validator, CLI, and browser build. The typical buyer is a backend or full-stack developer automating transactional or marketing email generation in Node.js.
mjml/ - Top-level package: wires preset-core components into mjml2html, main entry pointmjml-accordion/ - Accordion component (interactive collapsible sections for email clients that support it)mjml-body/ - mj-body component, root email body wrapper with width and background-colormjml-browser/ - Webpack bundle + browser mocks for running MJML in a browser environmentmjml-button/ - mj-button component, styled call-to-action anchor elementmjml-carousel/ - mj-carousel and mj-carousel-image components for image carouselsmjml-cli/ - Command-line interface for compiling .mjml files to HTMLmjml-column/ - mj-column layout componentmjml-core/ - Core rendering engine, base component classes, HTML generation utilitiesmjml-divider/ - mj-divider horizontal rule componentmjml-group/ - mj-group multi-column grouping componentmjml-head/ - mj-head component for email head configurationmjml-head-attributes/ - mj-attributes global attribute defaultsmjml-head-breakpoint/ - mj-breakpoint responsive breakpoint declarationmjml-head-font/ - mj-font web font importmjml-head-html-attributes/ - mj-html-attributes custom HTML attribute injectionmjml-head-preview/ - mj-preview inbox preview textmjml-head-style/ - mj-style custom CSS injectionmjml-head-title/ - mj-title email subject/titleSpin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This Express backend / api completed archive review. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 fa52f04a10e4b515…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
mjml-hero/ - mj-hero full-width hero section componentmjml-image/ - mj-image responsive image componentmjml-navbar/ - mj-navbar navigation bar componentmjml-parser-xml/ - XML parser turning MJML markup into an ASTmjml-preset-core/ - Bundles all standard components and their dependency graphmjml-raw/ - mj-raw raw HTML passthrough componentmjml-section/ - mj-section horizontal section layoutmjml-social/ - mj-social social media icon linksmjml-spacer/ - mj-spacer vertical whitespace componentmjml-table/ - mj-table HTML table componentmjml-text/ - mj-text styled text blockmjml-validator/ - Validates MJML AST nodes against component attribute rulesmjml-wrapper/ - mj-wrapper full-width background wrappernpm install mjml mjml-core mjml-preset-core mjml-validator mjml-parser-xml
If you use the CLI:
npm install mjml-cli
For browser builds, mjml-browser uses webpack with custom mocks — run its webpack config separately; it is not a runtime npm dependency for Node.js consumers.
No native modules, no pod install, no Android linking required for Node.js usage.
Copy the source/ directory into your project root, e.g. as vendor/mjml/.
If your project uses TypeScript, add path aliases in tsconfig.json (the packages ship ES modules compiled via Babel):
{
"compilerOptions": {
"moduleResolution": "bundler",
"allowJs": true,
"esModuleInterop": true
}
}
.js ES-module source), ensure @babel/preset-env and @babel/plugin-proposal-class-properties are configured:{
"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
No mandatory environment variables. Optional env vars consumed by mjml-core:
MJML_CONFIG — path to a .mjmlconfig file (component registration overrides)Import from the top-level mjml package (or source/mjml/src/index.js):
import mjml2html from 'mjml'
async function mjml2html(
input: string,
options?: {
beautify?: boolean
minify?: boolean
validationLevel?: 'strict' | 'soft' | 'skip'
filePath?: string
fonts?: Record<string, string>
keepComments?: boolean
preprocessors?: Array<(xml: string) => string>
}
): Promise<{ html: string; errors: Array<{ tagName: string; message: string; line: number }> }>
The primary entry point. Pass a raw MJML string; receive compiled HTML and a list of validation errors. Use validationLevel: 'skip' in production when templates are pre-validated to skip runtime checks.
class MjBody extends BodyComponent {
static componentName: 'mj-body'
static allowedAttributes: {
width: 'unit(px)'
'background-color': 'color'
id: 'string'
}
static defaultAttributes: { width: '600px' }
getChildContext(): Record<string, unknown>
getStyles(): Record<string, Record<string, string>>
render(): string
}
The root body component. Extend this class when building custom wrapper components that need to participate in the child-context system (e.g., passing containerWidth downstream).
class MjButton extends BodyComponent {
static componentName: 'mj-button'
static endingTag: true
static allowedAttributes: Record<string, string>
static defaultAttributes: Record<string, string>
}
A self-contained call-to-action button component. Register it via assignComponents if you are composing a custom preset without mjml-preset-core. The endingTag: true flag means the component wraps inner text content rather than child MJML components.
export { Accordion, AccordionElement, AccordionText, AccordionTitle } from 'mjml-accordion'
Four cooperating components for interactive disclosure widgets. Register all four together; Accordion is the parent, and the three sub-components must be declared as its allowed children in your dependency map.
Render a simple notification email to HTML and write it to disk.
import mjml2html from './vendor/mjml/src/index.js'
import fs from 'fs/promises'
const template = `
<mjml>
<mj-head>
<mj-title>Order Confirmed</mj-title>
<mj-preview>Your order #1234 is confirmed.</mj-preview>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="20px" color="#333333">Hello, your order is confirmed!</mj-text>
<mj-button href="https://example.com/orders/1234">View Order</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml>
`
const { html, errors } = await mjml2html(template, { validationLevel: 'soft' })
if (errors.length) {
console.error('MJML validation errors:', errors)
}
await fs.writeFile('output.html', html, 'utf8')
console.log('Written output.html')
Serve compiled MJML as HTML from an Express endpoint for browser preview.
import express from 'express'
import mjml2html from './vendor/mjml/src/index.js'
const app = express()
app.use(express.json())
app.post('/preview-email', async (req, res) => {
const { mjmlSource } = req.body as { mjmlSource: string }
if (!mjmlSource) {
return res.status(400).json({ error: 'mjmlSource is required' })
}
const { html, errors } = await mjml2html(mjmlSource, {
beautify: true,
validationLevel: 'soft',
})
if (errors.length > 0) {
return res.status(422).json({ errors })
}
res.setHeader('Content-Type', 'text/html')
res.send(html)
})
app.listen(3000, () => console.log('Preview server on :3000'))
Use assignComponents and assignDependencies to add a custom component without replacing the full preset.
import mjml2htmlCore, { components, assignComponents } from './vendor/mjml-core/src/index.js'
import { dependencies, assignDependencies } from './vendor/mjml-validator/src/index.js'
import presetCore from './vendor/mjml-preset-core/src/index.js'
import { BodyComponent } from './vendor/mjml-core/src/index.js'
class MjCustomBanner extends BodyComponent {
static componentName = 'mj-custom-banner'
static endingTag = true
static defaultAttributes = { color: '#ff0000' }
render() {
return `<div style="color:${this.getAttribute('color')}">${this.getContent()}</div>`
}
}
assignComponents(components, {
...presetCore.components,
'mj-custom-banner': MjCustomBanner,
})
assignDependencies(dependencies, {
...presetCore.dependencies,
'mj-column': [...(presetCore.dependencies['mj-column'] ?? []), 'mj-custom-banner'],
})
const { html } = await mjml2htmlCore(
`<mjml><mj-body><mj-section><mj-column>
<mj-custom-banner color="#0055ff">Hello</mj-custom-banner>
</mj-column></mj-section></mj-body></mjml>`,
{}
)
console.log(html)
mjml/src/index.js - Bootstraps the compiler: loads mjml-core, attaches mjml-preset-core components and dependencies, then re-exports mjml2html as the async default.mjml-accordion/src/index.js - Re-exports all four accordion sub-classes for downstream registration.mjml-accordion/src/Accordion.js - Parent accordion container component with CSS toggle logic.mjml-accordion/src/AccordionElement.js - Individual collapsible row within an accordion.mjml-accordion/src/AccordionText.js - Body text content of an accordion element.mjml-accordion/src/AccordionTitle.js - Clickable title header of an accordion element.mjml-body/src/index.js - MjBody class; establishes containerWidth context for all children.mjml-body/src/helpers/preview.js - Renders the hidden preview-text <div> in the email body.mjml-browser/webpack.config.js - Webpack config that substitutes Node.js modules with browser-safe mocks.mjml-browser/browser-mocks/ - Stub implementations of fs, path, htmlnano, etc. for browser builds.mjml-button/src/index.js - MjButton CTA component with full attribute schema and padding/width calculation.mjml-carousel/src/index.js - Re-exports Carousel and CarouselImage for registration.mjml-carousel/src/Carousel.js - Master carousel component generating CSS radio-button interaction.mjml-carousel/src/CarouselImage.js - Individual carousel slide image component.mjml-cli/src/client.js - CLI entry, parses argv and delegates to command handlers.mjml-cli/src/commands/outputToConsole.js - Writes compiled HTML to stdout.mjml-core/ - Base BodyComponent class, mjml2html engine, context system, HTML attribute helpers.mjml-parser-xml/ - Converts raw MJML XML string into a structured AST consumed by mjml-core.mjml-preset-core/ - Aggregates all standard components and their allowed-children dependency map.mjml-validator/ - Exports dependencies map and assignDependencies; validates attribute types at compile time.__esModule / default import) — Set "esModuleInterop": true in tsconfig.json and use import mjml2html from 'mjml'; do not use require('mjml').default.static class fields syntax error in Node < 16 — Add @babel/plugin-proposal-class-properties or upgrade to Node 18+ which supports it natively.Unknown component error — You forgot to call assignComponents / assignDependencies before invoking mjml2htmlCore directly; always use the top-level mjml package or replicate its bootstrap.htmlnano optional minify dependency absent — minify: true requires htmlnano and postcss to be installed separately (npm install htmlnano postcss); the error is silent in some versions.fs / path imports — Use mjml-browser and its webpack config with the provided stubs; do not try to bundle mjml-core directly in a browser webpack target.validationLevel: 'strict' throws on unknown attributes — Third-party or custom components must be registered before compilation; use 'soft' during development to receive errors as an array rather than thrown exceptions.I have purchased a source-available copy of the MJML email compiler monorepo.
The source is located in the `source/` directory of this project.
A detailed integration guide is in `source/USAGE.md`.
The upstream package name is `mjml` (npm: mjml).
Please help me integrate MJML into my existing Node.js/TypeScript project
step by step:
1. Read `source/USAGE.md` thoroughly before writing any code.
2. Install only the npm dependencies listed in the "Required dependencies"
section — do NOT install `mjml` from npm; we are using the local source.
3. Configure Babel/TypeScript as described in "Project setup".
4. Create a `src/email/compiler.ts` module that exports a `compileEmail`
function wrapping `mjml2html` from `source/mjml/src/index.js`.
5. Add an Express route `POST /api/send-email` that accepts a JSON body
`{ to, mjmlSource }`, compiles the template, and logs the resulting HTML.
6. Show me any validation errors as structured JSON, not thrown exceptions.
7. Reference the real exports shown in USAGE.md — do not invent any APIs.
8. After each step, confirm which file you modified and what you changed.
MJML is licensed under the MIT License. See source/LICENSE if present, or refer to the official repository for the full license text. Developed originally by Mailjet. Upstream package: mjml on npm.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
PHP, Laravel & Business Scripts
Free