Back to Mjml

Install

doc/install.md

5.1.022.1 KB
Original Source

Installation

You can install MJML with NPM to use it with NodeJS or the Command Line Interface. If you're not sure what those are, head over to Usage for other ways to use MJML.

bash
npm install mjml

Development

To work on MJML, make changes and create pull requests, download and install yarn for easy development.

bash
git clone https://github.com/mjmlio/mjml.git && cd mjml
yarn
yarn build

You can also run yarn build:watch to rebuild the package as you code.

Usage

Online

Don't want to install anything? Use the free online editor!

<figure> </figure> <p class="cta-container"><a class="cta" href="https://mjml.io/try-it-live">Try it live</a></p>

Applications and plugins

MJML comes with an ecosystem of tools and plugins, check out:

For more information, check the Tooling section.
For more tools, check the Community page.

Command line interface

Compiles the file and outputs the HTML generated in output.html

bash
mjml input.mjml -o output.html

You can pass optional arguments to the CLI and combine them.

argumentdescriptiondefault value
mjml [input] -o [output]Writes the output to [output]
mjml [input] -sWrites the output to stdout
mjml [input] -s --noStdoutFileCommentWrites the output to stdout without an comment containing the source file in the first linethe outputs first line contains the file in the format <!-- FILE: {filename} -->
mjml -w [input]Watches the changes made to [input] (file or folder)
mjml [input] --config.allowIncludesEnables mj-include processing (true or false)false
mjml [input] --config.allowMixedSyntaxAllow mixing block tokens (e.g. {%...%}) with CSS tokens (e.g. color: {{...}}) in the same documentfalse
mjml [input] --config.beautifyBeautifies the output (true or false)true
mjml [input] --config.includePathAdds allowlisted include root(s), as a string path or JSON array of paths
mjml [input] --config.juicePreserveTagsPreserve some tags when inlining css, see mjml-cli documentation for more info
mjml [input] --config.minifyMinifies the output (true or false)false
mjml [input] --config.minifyOptionsOptions for HTML minifier. Use minifyCss to control CSS minification (legacy: minifyCSS is still accepted). See mjml-cli documentation for more info
mjml [input] --config.mjmlConfigPath [mjmlconfigPath]Uses the .mjmlconfig file in the specified path or directory to include custom componentsThe .mjmlconfig file in the current working directory, if any
mjml [input] --config.sanitizeStylesOptional setting when using templating syntax to sanitize the input to PostCSS preventing (true or false) errorsfalse
mjml [input] --config.templateSyntaxJSON array of { prefix, suffix } objects to declare templating delimiters (used by sanitization and restore)
mjml [input] --config.useMjmlConfigOptionsAllows to use the options attribute from .mjmlconfig filefalse
mjml [input] --config.validationLevelValidation level: strict, soft or skipsoft

Minify options compatibility

CSS minification is controlled via minifyCss. For backward compatibility, the legacy minifyCSS key is still accepted and mapped internally:

  • Disable CSS minification:
bash
mjml input.mjml -o output.html --config.minify true --config.minifyOptions '{"minifyCss": false}'
# legacy:
mjml input.mjml -o output.html --config.minify true --config.minifyOptions '{"minifyCSS": false}'
  • Enable CSS minification with presets or options:
bash
# lite preset
mjml input.mjml -o output.html --config.minify true --config.minifyOptions '{"minifyCss": "lite"}'
# legacy equivalent (maps to lite)
mjml input.mjml -o output.html --config.minify true --config.minifyOptions '{"minifyCSS": true}'
# default preset with single quotes for strings
mjml input.mjml -o output.html --config.minify true --config.minifyOptions '{"minifyCss": {"preset":["default", {"normalizeString":{"preferredQuote":"single"}}]}}'

Inside Node.js

javascript
import mjml2html from 'mjml'

/*
  Compile an mjml string
*/
async function renderMjml() {
  const htmlOutput = await mjml2html(
    `
    <mjml>
      <mj-body>
        <mj-section>
          <mj-column>
            <mj-text>
              Hello World!
            </mj-text>
          </mj-column>
        </mj-section>
      </mj-body>
    </mjml>
  `,
    options,
  )

  /*
    Print the responsive HTML generated and MJML errors if any
  */
  console.log(htmlOutput)
}

renderMjml()

You can pass optional options as an object to the mjml2html function:

optionacceptsdescriptiondefault value
allowMixedSyntaxbooleanAllow mixing block tokens and CSS tokens within the same document when sanitizing/minifying CSSfalse
beautifybooleanOption to beautify the HTML outputfalse
filePathstringPath of the input file or a base directory; determines the default include sandbox (includes are allowed only under this directory when enabled)'.'
ignoreIncludesbooleanOption to ignore mj-include instancestrue
includePathstring or array of stringsOne or more explicit directories where includes are allowed, in addition to filePath. Paths outside these directories are denied.
fontsobjectDefault fonts imported in the HTML rendered by MJMLSee in index.js
juicePreserveTagsobjectOptional setting when inlining CSS, see mjml-cli documentation for more info
keepCommentsbooleanOption to keep comments in the HTML outputtrue
minifybooleanOption to minify the HTML outputfalse
minifyOptionsobjectOptions for HTML minifier, see mjml-cli documentation for more info{"collapseWhitespace": true, "minifyCss": "lite", "removeEmptyAttributes": true}

minifyCss can be false, lite, default, or a cssnano preset object, for example minifyCss: { preset: ['default', { normalizeString: { preferredQuote: 'single' } }] } | | mjmlConfigPath | string | The path or directory of the .mjmlconfig file | process.cwd() | | preprocessors | array of functions | Preprocessors applied to the xml before parsing. Functions must be (xml: string) => string | [] | | sanitizeStyles | boolean | Optional setting when using templating syntax to sanitize the input to PostCSS preventing errors | false | | templateSyntax | array of objects | When sanitizeStyles is true, you can pass optional syntax e.g. templateSyntax: [{ prefix: '{{', suffix: '}}' }, { prefix: '{=', suffix: '=}' }] | [{"prefix":"{{","suffix":"}}"},{"prefix":"[[","suffix":"]]"}] | | useMjmlConfigOptions | boolean | Allows to use the options attribute from .mjmlconfig file | false | | validationLevel | string | Available values for the validator: strict soft skip | soft |

Include path examples

Includes are ignored by default for security (ignoreIncludes: true). Enable them explicitly and scope allowed folders with includePath.

CLI example:

bash
$> mjml template.mjml \
  --config.filePath /project/templates/newsletter \
  --config.allowIncludes true \
  --config.includePath '["../_common","../vendor"]'
  • Single include directory
js
import mjml2html from 'mjml'

async function compileOne(source) {
  const { html, errors } = await mjml2html(source, {
    ignoreIncludes: false,
    filePath: '/project/templates/campaignA/email1.mjml',
    includePath: '/project/templates/_common',
  })
}
  • Multiple include directories
js
async function compileMany(source) {
  const { html, errors } = await mjml2html(source, {
    ignoreIncludes: false,
    filePath: '/project/templates/campaignA/email1.mjml',
    includePath: ['/project/templates/_common', '/project/templates/_footers'],
  })
}

Security notes:

  • Includes are ignored by default (ignoreIncludes: true). Enable explicitly and scope allowed folders with includePath.
  • Paths are fully URL-decoded before validation (handles double/triple encoding like %252F).
  • Early rejects: absolute paths, UNC-style paths (//server/... or \\server\\...), Windows drive letters (C:\...), and null bytes (%00).
  • Canonical boundary checks: we resolve and follow symlinks with realpath and require the target to stay inside filePath or any includePath roots.

Best practices for shared partials

  • Project templates root: Set filePath to your templates root and write includes relative to that base (e.g., ./_common/header.mjml). Simple setup; templates must use base-relative paths.
  • Explicit allowlist: Keep template-relative paths (e.g., ../_common/header.mjml) and declare includePath with sibling/shared folders. No template changes; supports multiple shared roots.
  • Security: Only files under filePath and includePath are allowed. Absolute paths outside these roots and .. escapes are denied.

API

A free-to-use MJML API is available to make it easy to integrate MJML in your application. Head over here to learn more about the API.