grapesjs-mjml: MJML components inside a GrapesJS editor
Newsletter Builder with MJML components in GrapesJS
At a glance
- What is it?
- grapesjs-mjml is a GrapesJS plugin that adds MJML newsletter components to the visual editor and renders them in real time with the official MJML v4 compiler running in the browser. It is aimed at teams building a drag-and-drop email builder on top of GrapesJS, and its behaviour is shaped by a long list of reset-style options.
- Who is it for?
- grapesjs-mjml fits a team that has already chosen GrapesJS and needs email templates built from MJML rather than free-form HTML, with a preview that matches the MJML Live Editor. It does not fit someone who needs a standalone email editor, or a project that must compile MJML on a server with strict output validation, since the rendering path here runs in the browser.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 130 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A newsletter builder that edits MJML rather than raw HTML
grapesjs-mjml is a plugin that enables the use of MJML components inside the GrapesJS environment, and it requires GrapesJS v0.15.9 or higher. The problem it solves is specific: MJML is a markup abstraction for email, but a drag-and-drop editor that produces arbitrary HTML will not produce MJML, and an editor that understands MJML has to expose a component tree rather than a free canvas of tags. The plugin resolves that by mapping MJML tags onto GrapesJS components, so the editor shows a structure of sections, columns and text blocks, and the exported artefact is MJML markup. The audience is a product team assembling an email or newsletter builder on top of GrapesJS, who want the constrained structure of MJML and its responsiveness rules without asking users to write any of it by hand.
Real-time rendering through the official v4 compiler
The mechanism is that MJML components are rendered in real time using the official v4 compiler, with some mocks to make it run in the browser, and the README states that the result is almost the same as using the MJML Live Editor. That is the core value, because MJML normally renders as a server-side tool producing an HTML table layout, and a browser editor needs that output live on every change. The package dependencies confirm the approach: mjml-browser at version 4.18.0 is a runtime dependency, not a build-time one, and the type definitions for MJML come alongside it. The set of supported components follows the default mjml-browser parser, and the README lists them explicitly, from mj-mjml, mj-head and mj-body down through mj-section, mj-column, mj-text, mj-image, mj-button, mj-social, mj-divider, mj-spacer, mj-style, mj-font, mj-hero, mj-navbar, mj-raw and the rest.
The options list is really a list of resets
Most of the plugin options are switches that decide what the editor looks like when the plugin loads. resetBlocks cleans all previous blocks, resetDevices cleans all previous devices and sets a new one for mobile, resetStyleManager resets the Style Manager and adds new properties for MJML, and hideSelector hides the default selector manager. On the content side, blocks selects which blocks to add and defaults to all of them, while block adds custom block options based on the block id with a default of (blockId) => ({}). The export side is controlled by overwriteExport, which overwrites the default export command and is true by default, plus preMjml and postMjml for inserting a string before or after the MJML in the export code. columnsPadding sets a default of 10px 0 for column padding, described as making columns easier to select, and useXmlParser is flagged as experimental for importing void MJML elements such as mj-image without closing tags.
Adding the plugin with npm and the pluginsOpts block
The plugin is installed from npm as a normal GrapesJS plugin, and the README's Download section gives the package name as grapesjs-mjml to install with npm i grapesjs-mjml. In the browser, three assets are needed, the GrapesJS stylesheet, the GrapesJS script and the plugin script:
<link href="path/to/grapes.min.css" rel="stylesheet"/>
<script src="path/to/grapes.min.js"></script>
<script src="path/to/grapesjs-mjml.min.js"></script>The editor is then initialised against a container element. The ESM form is shorter and is what a modern build would use:
import 'grapesjs/dist/css/grapes.min.css'
import grapesJS from 'grapesjs'
import grapesJSMJML from 'grapesjs-mjml'
grapesJS.init({
fromElement: true,
container: '#gjs',
plugins: [grapesJSMJML],
pluginsOpts: {
[grapesJSMJML]: {/* ...options */}
},
});Note fromElement: true, which tells GrapesJS to read the initial content from the container element, and the fact that plugin options are passed inside pluginsOpts keyed by the plugin object. The container holds a starting mjml tree with mj-body, mj-section, mj-column and mj-text elements.
Plugging in your own mjml-browser build and custom components
If your organisation runs a custom or extended MJML, the plugin lets you swap the parser rather than accepting the default one. The mjmlParser option takes a mjml-browser instance and its documented signature is (input: string | MJMLJsonObject, opt: MJMLParsingOptions) => MJMLParseResults, which is the extension point. Alongside it, customComponents takes a list of components that are added to the default set, and the README notes that the default components live in a components folder in the repository. The usage example passes both, with a custom parser imported from custom-mjml-parser and a custom image component imported from custom/components/path:
import 'grapesjs/dist/css/grapes.min.css'
import grapesJS from 'grapesjs'
import grapesJSMJML from 'grapesjs-mjml'
import customMjmlParser from 'custom-mjml-parser';
import customImage from 'custom/components/path'The README points to the GrapesJS documentation for defining a custom component type, so the work involved is GrapesJS component authoring plus your own MJML tag, not a fork of the plugin.
Localisation covers the editor chrome and the plugin separately
The plugin carries its own translation layer, and the usage example shows that it is configured apart from the editor's. GrapesJS itself takes a locale bundle such as grapesjs/locale/nl and an i18n object with a locale, an optional detectLocale flag and a localeFallback, while the plugin takes a matching bundle such as grapesjs-mjml/locale/nl and its own i18n key inside pluginsOpts. The i18n option in the plugin's option table is an object containing the language. This split matters when you build a localised editor, because a missing plugin bundle leaves plugin-specific labels in the fallback language while the rest of the interface is translated. The plugin also ships an image placeholder source, defaulting to a via.placeholder.com URL, and an importPlaceholder template for the import modal, both of which you would replace in a production build rather than ship as they are.
A version 1.0 package with a scripted release, and no releases since March
The release process is written down, which is more than many plugins offer. The version bump is npm run v:patch, which runs npm version patch with the message Release v%s and creates a git tag. The commit and tag are pushed, a draft release is created on GitHub with notes attached to the new tag, and publishing it releases to npm automatically. The build itself runs through the GrapesJS CLI, with the build script using grapesjs-cli build --patch=false, and tests run under jest while linting uses eslint on the src directory. The package is BSD 3-Clause licensed and publishes the dist and locale directories. On the versions, v1.0.8 was released on 2026-03-13, v1.0.7 on 2025-07-24 and v1.0.6 on 2024-08-26, and the last push to the repository was on 2026-06-15. Development dependencies list grapesjs at ^0.21.2, so the plugin is developed against a GrapesJS well past the 0.15.9 minimum it declares.
Editorial conclusion
grapesjs-mjml fits a team that has already chosen GrapesJS and needs email templates built from MJML rather than free-form HTML, with a preview that matches the MJML Live Editor. It does not fit someone who needs a standalone email editor, or a project that must compile MJML on a server with strict output validation, since the rendering path here runs in the browser. Before adopting it, confirm your GrapesJS version is 0.15.9 or higher, decide whether the default option resets that clear your existing blocks, devices and Style Manager properties are acceptable, and read the customComponents and mjmlParser options if your brand components are not standard MJML.
Frequently asked questions
How do I install grapesjs-mjml and add it to a GrapesJS editor?
Install it with npm i grapesjs-mjml, then pass it into the plugins array of grapesJS.init and give it its options under pluginsOpts. The plugin requires GrapesJS v0.15.9 or higher, and the ESM example in the README is the shortest way to wire it up.
How does grapesjs-mjml render MJML in the browser?
The plugin renders MJML components in real time with the official v4 compiler, plus mocks so it can run in the browser, and the README says the result is almost the same as the MJML Live Editor. The compiler comes from the mjml-browser package, which is a runtime dependency.
Can I add my own MJML components to the editor?
Yes. The customComponents option takes a list of components that are added to the default set, and the mjmlParser option accepts a custom mjml-browser instance so you can extend MJML itself. The README points to the components folder in the repository and to the GrapesJS documentation for defining a custom component type.
What licence is grapesjs-mjml under?
BSD 3-Clause, stated in the README and in the package.json license field, with the LICENSE file at the root of the repository. The published package includes the dist and locale directories.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/grapesjs-mjml)Was this useful?