This is a bolierplate that helps getting started with generating responsive e-mail templates with Franklin using mjml.
It in particular inherits the Authoring Experience and Developer Experience from Franklin for, the Delivery is signifiicantly different though.
As E-Mail clients usually do not support Javascript the fully rendered E-Mail template is made available to the author to Copy & Paste it in their preferred Marketing Automation tool, or to directly downloaded it and send it with a local E-Mail client.
As with other Franklin projects the decoration of the DOM happens clientside, in the author's browsers when previewing a document.
As usual the project scripts decorate the DOM as it gets served from the franklin html pipeline (icons, auto-blocking, sections, blocks, ...). Afterwards the decorated DOM is used to create an mjml E-Mail template, which gets transpiled into E-Mail friendly HTML. This HTML is than presented to the user in an iframe that fully covers the original page.
Sidekick extensions allow the author to copy or download the generated HTML.
Default content, like texts, lists buttons and images are supported:
<img>
get transformed to<mj-image>
<a>
inside of.button-container
s get transformed to<mj-button>
- all other types of paragraphs (
<p>
,<ul>
,<h1>
,<h2>
, ...) get wrapped into<mj-text>
The scripts.js module exports a function to make this logic reusable for blocks that wrap default content, like the columns block.
Other than in Franklin for Web projects the blocks in this boilerplate do not decorate the given DOM but have to return an mjml-string instead.
export default async function(block) {
return `
<mj-section>
<mj-column>
<mj-text>Hello World</mj-text>
</mj-column>
</mj-section>
`;
}
These mjml-strings get than concatenated to generate the contents of the mjml template body.
It is important to mention that the output of a block needs to be wrapped in a <mj-section>
and <mj-column>
.
The following blocks are availabe as part of the boilerplate:
- Columns using
<mj-column>
- Accordion using
<mj-accordion>
- Carousel using
<mj-carousel>
- Hero using
<mj-section>
with a background image - Table using
<mj-table>
Stylesheets get fetched and included into the mjml template's head. There are two global stylesheets
email-styles.css and email-inline-styles.css. As the name
suggest the later will be included with <mj-style inline="inline">
which will inline the styles into the markup.
Declarations that cannot be inlined like media queries, pseudo selectors or selectors that target boilerplate elements
injected by email clients should be kept in the respective stylesheet that does not get inlined.
Blocks can export stylesheets as well. Per default a single css file is fetched for each blocked and treated as inline
style. However the block module can provide two named exports styles
and inlineStyles
to specify which stylesheets
to fetch and how to treat them.
Keep in mind that it is necessary to set a css-class
attribute in mjml to add a class to the rendered html.
⚠️ Using attributes is preferred over using css styles.
Most of the styles can be applied with attributes on the the mjml elements themself. These will be inlined similar to inline styles. However, especially for styles of the box model (width, borders, paddings, ...) the values are also taken into account to calculate absolute values for clients that do not have full support for the box model (e.g. Outlook).
To make setting the mjml attributes as easy as styling the DOM with css this boilerplate supports the definition of
[<mj-attributes>
] in css files. In fact each fetched stylesheet is parsed, some rules removed from the and added
to the mj-head as mjml attributes instead. This includes:
-
rules with a tag selector for mjml elements inlcuding
mj-all
, e.g.mj-button { border-radius: 2px, background-color: orange; } mj-all { font-size: 15px; font-family: Arial}
will be included in the
<mj-head>
as<mj-attributes> <mj-button border-radius="2px" background-color="orange"/> <mj-all font-size="15px" font-family="Arial"> </mj-attributes>
-
rules with class selectors that start with
.mj-
or are specific tomj-all
, e.g..mj-hero-spacer { height: 180px } .mj-hero-text { color: white } mj-all.highlight { background-color: #bfbfbf; }
will be included in the
<mj-head>
as<mj-attributes> <mj-class name="mj-hero-spacer" height="180px"/> <mj-class name="mj-hero-text" color="white"/> <mj-class name="highlight" background-color="#bfbfbf"/> </mj-attributes>
-
rules that target only a specific template (a class on the
<body>
of the original DOM), e.g..newsletter-spring-2022 .mj-hero-spacer { height: 200px } .newsletter-spring-2022 mj-button { color: white; background-color: orange }
will only be included when the first element of the selectors matches the document body:
<html> <body class="newsletter-spring-2022"> ... </body> </html>
npm i
npm tst
- Create a new repository based on the
helix-project-boilerplate
template and add a mountpoint in thefstab.yaml
- Add the helix-bot to the repository
- Install the Helix CLI:
npm install -g @adobe/helix-cli
- Start Helix Pages Proxy:
hlx up
(opens your browser athttp://localhost:3000
) - Open the
{repo}
directory in your favorite IDE and start coding :)