Configuration

Maizzle uses Jigsaw's config.php files to allow for environment-specific configurations. These are PHP arrays with key-value pairs that define certain settings, and can even include functions.

This gives you the freedom to define distinct settings for any build scenario you need, ranging from quick local development, to staging builds or production-ready emails.

Default Config

Maizzle's config.php is well-commented, so you understand what settings do right away:

/*

Maizzle - Email Development Framework

A project by Cosmin Popovici (@cossssmin) and ThemeMountain (@thememountainco).

Welcome to the Maizzle config file. This is where you can customise some
Maizzle settings for your project.

View the full documentation at https://maizzle.com/docs

|-------------------------------------------------------------------------------
| The default config                   https://maizzle.com/docs/building/#local
|-------------------------------------------------------------------------------
|
| This array contains the default Maizzle settings for development. This is
| used when you run the `npm run dev` or `npm run watch` commands.
|
*/

return [

    /*
    |-----------------------------------------------------------------------------
    | Layout                                    https://maizzle.com/docs/layouts/
    |-----------------------------------------------------------------------------
    |
    | Define a master layout that all templates will extend by default.
    |
    | Maizzle comes with a default layout that sets various tags to
    | use settings from your config, but you can of course create
    | your own layouts and extend them at a template level,
    | with front matter.
    |
    */
    'extends' => '_layouts.master',

    /*
    |-----------------------------------------------------------------------------
    | Doctype                     https://maizzle.com/docs/configuration/#doctype
    |-----------------------------------------------------------------------------
    |
    | Define a doctype that will be used in the layout your emails extend.
    |
    | Maizzle defines an HTML 5 doctype by default, but you can choose
    | any doctype you need. You can also override it for each email,
    | through a front matter variable. If you use an empty string,
    | Maizzle's layouts will fallback to `html`.
    |
    */
    'doctype' => 'html',

    /*
    |-----------------------------------------------------------------------------
    | Language                   https://maizzle.com/docs/configuration/#language
    |-----------------------------------------------------------------------------
    |
    | This will be used in the `lang=""` attribute of the `<html>` tag. It helps
    | screen reader software use the correct pronunciation. Of course, you can
    | override it in each template, with front matter variables.
    |
    */

    'language' => 'en',

    /*
    |-----------------------------------------------------------------------------
    | Character set               https://maizzle.com/docs/configuration/#charset
    |-----------------------------------------------------------------------------
    |
    | Character encoding is set to UTF-8 by default. This prevents breaking
    | reading patterns by ensuring proper character rendering, both
    | on-screen and with screen readers.
    |
    */

    'charset' => 'utf8',

    /*
    |-----------------------------------------------------------------------------
    | Document title                https://maizzle.com/docs/configuration/#title
    |-----------------------------------------------------------------------------
    |
    | The `<title>` tag is needed in order to give screen reader users context.
    | It also helps when viewing the email in a browser (like your email's
    | online version), by setting the title on the browser's tab.
    |
    | You should specify a `title` key in the front matter for each email.
    |
    */

    'title' => '',

    /*
    |-----------------------------------------------------------------------------
    | Google Fonts           https://maizzle.com/docs/configuration/#google-fonts
    |-----------------------------------------------------------------------------
    |
    | This is where you can define which Google Fonts Maizzle should import.
    |
    | It will only import Google Fonts by adding a `<link>` tag to your HTML.
    | In order to use them, you still need to register the .font-{name}
    | class in the tailwind.js config file. Use as few fonts and
    | weights as possible, because it affects load time.
    |
    | Example:
    |
    | 'googleFonts' => [
    |    'Open+Sans:300,400,700',
    |    'Merriweather',
    | ],
    |
    */

    'googleFonts' => [],

    /*
    |-----------------------------------------------------------------------------
    | Screenshots                  https://maizzle.com/docs/building/#screenshots
    |-----------------------------------------------------------------------------
    |
    | This is where you can define which devices Puppeteer should emulate when
    | using the `screenshots` command in Maizzle. iPad Mini and iPhone 6 are
    | enabled by default, but you can use any of the device descriptors
    | supported by Puppeteer.
    |
    | It is recommended that you use as few devices as possible, as this
    | process launches Chrome in headless mode and, the more devices
    | you use, the more time it will take to generate screenshots.
    |
    | Note that these only emulate the viewport of a device, they are not
    | intended for email client render tests.
    |
    */

    'screenshots' => [
        'devices' => [
            'iPad Mini',
            'iPhone 6',
        ],
        'type' => 'png',
        'quality' => 100,
    ],

    /*
    |-----------------------------------------------------------------------------
    | Transformers           https://maizzle.com/docs/configuration/#transformers
    |-----------------------------------------------------------------------------
    |
    | This is where you can define various transformations that will be applied
    | to the output files. To speed up development, Maizzle disables most of
    | them for local development. They are, however, enabled in the
    | staging and production environment configs.
    |
    | Don't let the output file size scare you when working locally. Having
    | transformations disabled, you can reference any Tailwind CSS class
    | when debugging in-browser, and rapidly prototype your emails.
    |
    | Some of the advanced minifier options are not exposed here, but you
    | can customise them in tasks/js/after-jigsaw.js.
    |
    */

    'transformers' => [
        'baseImageURL' => '',
        'inlineCSS' => [
            'enabled' => false,
            'styleToAttribute' => [
                'background-color' => 'bgcolor',
                'background-image' => 'background',
                'text-align' => 'align',
                'vertical-align' => 'valign',
            ],
            'applySizeAttribute' => [
                'width' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
                'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
            ],
            'excludedProperties' => [],
        ],
        'cleanup' => [
            'removeUnusedCss' => [
                'enabled' => false,
                'whitelist' => [
                    ".External*",
                    ".ReadMsgBody",
                    ".yshortcuts",
                    ".Mso*",
                    "#outlook",
                ],
                'backend' => [
                  [
                    'heads' => "{{",
                    'tails' => "}}",
                  ],
                ],
                'removeHTMLComments' => [
                    'enabled' => true,
                    'preserve' => ['if', 'endif', 'mso', 'ie'],
                ],
                'uglifyClassNames' => true,
            ],
            'keepOnlyAttributeSizes' => [
                'width' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
                'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
            ],
            'preferBgColorAttribute' => false,
        ],
        'prettify' => false,
        'minify' => [
            'minifyCSS' => false,
            'maxLineLength' => false,
            'preserveLineBreaks' => false,
            'collapseWhitespace' => false,
            'conservativeCollapse' => false,
        ],
        'sixHex' => false,
        'altText' => false,
    ],

    /*
    |-----------------------------------------------------------------------------
    | Plaintext                 https://maizzle.com/docs/configuration/#plaintext
    |-----------------------------------------------------------------------------
    |
    | When this option is set to true, Maizzle will generate a plaintext version
    | for every template. The .txt file will be placed in the same directory
    | as the HTML it's based on, and it will also have the same name.
    |
    */

    'plaintext' => false,

    /*
    |-----------------------------------------------------------------------------
    | BrowserSync             https://maizzle.com/docs/configuration/#browsersync
    |-----------------------------------------------------------------------------
    |
    | Tunnel
    |
    | When running the `watch` command with `tunnel` set to `true`, BrowserSync
    | will create a tunnel to your localhost, via localtunnel.me. You can
    | use this URL to share a live preview of what you're working
    | on with a colleague or a client.
    |
    | By default, setting it to `true` will generate a random localtunnel.me
    | subdomain. You can use a string instead, to have BrowserSync attempt
    | to use a custom subdomain.
    |
    | Directory listing
    |
    | Setting the `listing` option to `true` will enable a directory listing
    | when running the `watch` command, so you can browse through your
    | emails. You might want to set it to `false` when using the
    | tunnel option with a client.
    |
    */

    'browsersync' => [
        'tunnel' => false,
        'listing' => false,
    ],

    /*
    |-----------------------------------------------------------------------------
    | Helpers                     https://maizzle.com/docs/configuration/#helpers
    |-----------------------------------------------------------------------------
    |
    | Jigsaw config functions used by Maizzle in the build process.
    |
    */

    'googleFontsString' => function($page) {
        return collect($page->googleFonts)->transform(function($item, $key) {
            return str_replace(' ', '+', $item);
        })->implode('|');
    },

    /*
    |-----------------------------------------------------------------------------
    | Build defaults       https://maizzle.com/docs/configuration/#build-defaults
    |-----------------------------------------------------------------------------
    |
    | Configure additional Jigsaw build settings.
    |
    */

    'baseUrl' => '',
    'pretty' => false,
    'production' => false,
    'build' => [
        'source' => 'source',
        'destination' => 'build_local',
    ],
];

Environments

Use environment configurations and NPM scripts to define settings and compile emails for different scenarios.

Think of them like this:

When I run this command, should X happen? Should CSS be inlined? Should my HTML be minified? Do I need some data to be available for the templates?

Environment-based configurations are supported out of the box by Jigsaw, and can be defined by simply duplicating the default config.php to include the desired environment in the file name.

Local

config.php is for local development. No CSS is purged from your final emails and no inlining takes place, so that you can quickly prototype emails with all of Tailwind's classes at your disposal, for tinkering in the browser.

This one has the fastest build time, as almost no post-processing takes place.

Staging

Use config.staging.php to build emails that you share with your team. This one enables post-processing similar to production builds, but it prettifies code so that other humans get nicely-formatted, readable code.

Production

Finally, Maizzle also provides a config.production.php file, which enables the most transformations, such as CSS inlining, unused CSS purging, and even email-optimised HTML minification.


But you can go even further, and create your own, custom environments.

For example, you could create an environment config for a certain client or brand, like config.mystore.php or config.someclient.php - all with their own, customised Maizzle settings.

As the Jigsaw docs mention, custom environment configurations are merged on top of the default config.php ones. This means that a custom environment can overwrite settings in the default config, and it can also omit some.

The default configs in Maizzle do this too - you'll find the staging/production configs contain keys not present in the config.php file. At the same time, some keys are missing, because they're already defined in the default config.


Let's have a look at all the default options Maizzle comes with.

Layouts

'extends' => '_layouts.master',

Maizzle uses "master" pages, called Layouts.

A layout tipically contains the base HTML of a site (or, in our case, an email): things like the <head> tag, the <body> tag, and the main content wrapper.

Instead of always having to write it for each page, you simply extend it from a page, thus reusing the same layout file. Learn more in the Laravel Blade docs and Jigsaw docs.

Blade-Markdown automatic extends

Maizzle defines an extends key in the default config, so that if you use .blade.md files, they will extend this layout automatically. No need to extend with Front Matter for each email 👍

Doctype 1.1.0

'doctype' => 'html',

By default, Maizzle sets a HTML 5 doctype for your emails. This is used in the master.blade.php layout, and will default to html if it's not set in the config:

<!DOCTYPE {!! $page->doctype ?? 'html' !!}>

You can, of course, set this for each email in particular, through Front Matter:

---
doctype: html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
title: Confirm your email
preheader: Please verify your email address with us
---

Language

'language' => 'en',

The language key is used to define a content language for your emails. Maizzle uses it in the lang="" attribute on the <html> tag inside the master.blade.php layout file, and it defaults to en:

<html lang="{{ $page->language ?? 'en' }}" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">

Specifying it in Front Matter will change it only for that email:

---
language: ro
title: Verificare adresă de email
preheader: Te rugăm să ne confirmi adresa de email
---

Charset

'charset' => 'utf8',

This option is used to set the default character encoding, defaulting to UTF-8:

<meta charset="{{ $page->charset ?? 'utf8' }}">

Most likely, you won't need to change this.

Title

'title' => 'Maizzle - Build HTML emails fast, with TailwindCSS and Jigsaw',

Used to enable the <title></title> tag in your email template. If empty, the tag will not be inserted:

@if($page->title)<title>{{ $page->title }}</title>@endif

As you saw in the previous examples, each email can specify the title in Front Matter.

For accessibility reasons, it's recommended that you always add a title. As a bonus, if you're using the same email for your newsletter's 'web version', the browser tab will be informative.

Google Fonts

The 'googleFonts' key is an array with Google Fonts font names in Google's specific string formatting, that Maizzle should pull into your template.

By default, Maizzle pulls in Open Sans and Merriweather:

'googleFonts' => [
    'Open+Sans:300,400,700',
    'Merriweather',
],

If this array is empty, the <link> tag containing the Google Fonts import will not be added:

@if($page->googleFonts)
  <!--[if !mso]><!--><link rel="stylesheet" href="https://fonts.googleapis.com/css?family={{ $page->googleFontsString() }}"><!--<![endif]-->
@endif

The $page->googleFontsString() in the code above is a function that is also defined in config.php. It simply collects all Google Fonts you've specified, and returns a formatted string that we can use in the <link> tag:

'googleFontsString' => function($page) {
    return collect($page->googleFonts)->transform(function($item, $key) {
        return str_replace(' ', '+', $item);
    })->implode('|');
},

Screenshots

The screenshots array contains settings for Maizzle's Screenshots functionality.

You can use any device descriptors that Puppeteer knows about, and you can specify the screenshot file type and quality (quality applicable only to JPG).

'screenshots' => [
    'devices' => [
        'iPad Mini',
        'iPhone 6',
    ],
    'type' => 'png',
    'quality' => 100,
],

Transformers

Transformers control how the email magic happens: they enable various post-processing scripts that optimise your HTML for email. Examples show all options, but will vary between environments.

baseImageURL

'baseImageURL' => '',

If set to a valid URL, all image paths in your email (both inline and background images) will have this URL prepended. Useful if you already host your images somewhere, so you don't have to write the full URL every time when developing.

Usage:'baseImageURL' => 'https://cdn.example.com/some/folder/',

Note: use the trailing slash (/) at the end of your URL only if your image paths don't start with one.

inlineCSS

'inlineCSS' => [
    'enabled' => true,
    'styleToAttribute' => [
        'background-color' => 'bgcolor',
        'background-image' => 'background',
        'text-align' => 'align',
        'vertical-align' => 'valign',
    ],
    'applySizeAttribute' => [
        'width' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
        'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
    ],
    'excludedProperties' => [],
],

Uses Automattic's Juice library to inline CSS.

You can toggle this with the enabled boolean. When enabled, you can also define if Juice should remove the original <style></style> tags after (possibly) inlining the CSS from them, through 'removeStyleTags'.

removeStyleTags 1.0.2

This option has been removed from the configs in v1.1.0, because it was set to true in all environments.

It now defaults to true in the post-processing script, but you can opt-out by setting it to false:

'inlineCSS' => [
    'enabled' => true,
    'removeStyleTags' => false,
    // [...]
],

styleToAttribute 1.1.0

This option contains an array of rules that map CSS properties to HTML attributes. These are used by the Juice inliner to duplicate inline CSS as HTML attributes on table tags.

Opt-out by design

By default, Maizzle production configs include the styleToAttribute key, and populate it with Juice's defaults.

This is on purpose, for better email client compatibility.

However, if you specify a single mapping, like we did in the example above, Juice will only convert that to an attribute, keeping any other properties as inline CSS-only.

applySizeAttribute 1.1.0

This allows you to specify an array of elements that should receive width="" and height="" attributes. These elements will be passed to the Juice inliner, which will duplicate any inline width and height CSS rules it finds as HTML attributes, but only for those elements.

excludedProperties 1.1.0

The excludedProperties option allows you to define an array of CSS properties that should be excluded from the CSS inlining process by Juice:

'inlineCSS' => [
    'enabled' => true,
    // ...
    'excludedProperties' => [],
],

Maizzle sets this as an empty array in the production environment configs.

Property names are considered unique, so you need to specify each one you'd like to exclude. For example:

'excludedProperties' => ['padding', 'padding-left'],

cleanup

This key contains settings that you can use to clean up your email's code.

removeUnusedCss

These options are passed to email-remove-unused-css in order to safely remove unused CSS in your email. You can also define whether certain HTML comments should be removed, and if your CSS class names should be uglified so that they're much shorter (helps reduce HTML size):

'removeUnusedCss' => [
    'enabled' => true,
    'whitelist' => [
        ".External*",
        ".ReadMsgBody",
        ".yshortcuts",
        ".Mso*",
        "#outlook",
    ],
    'backend' => [
      [
        'heads' => "{{",
        'tails' => "}}",
      ],
    ],
    'removeHTMLComments' => [
        'enabled' => false,
        'preserve' => ['if', 'endif', 'mso', 'ie'],
    ],
    'uglifyClassNames' => false,
],

It is recommended to have removeUnusedCss enabled for production builds, as it reduces file size considerably.

Also, if you are just documenting your code, please note that you can use {{-- Blade comments --}} instead of <!-- regular HTML comments -->. Blade comments are not rendered in your compiled emails.

keepOnlyAttributeSizes 1.1.0

'cleanup' => [
    // [...]
    'keepOnlyAttributeSizes' => [
        'width' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
        'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
    ],
],

You can specify for which elements should the inline CSS width and height be removed. As you can see, Maizzle defaults to the same elements as in the applySizeAttribute option.

Removing the entire keepOnlyAttributeSizes key will leave any inline CSS width/height untouched.

Providing an empty array to one of its keys will not remove the corresponding CSS property for that key on any element. So if you do this:

'cleanup' => [
    // [...]
    'keepOnlyAttributeSizes' => [
        'width' => [],
        'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
    ],
],

... then any inline CSS width will be left untouched, while inline CSS height will be removed for all those elements specified in the array.

preferBgColorAttribute

'preferBgColorAttribute' => true,

This will remove the inline background-color: #...... CSS from tables, so they only use the HTML bgcolor="" attribute. Set to false if you want background colours set with both CSS and HTML attributes.

prettify

'prettify' => true,

When true, Maizzle will use pretty to beautify your email's HTML. It indents your code and makes it more readable - useful before sending it to another human.

minify

'minify' => [
    'minifyCSS' => false,
    'maxLineLength' => false,
    'preserveLineBreaks' => false,
    'collapseWhitespace' => false,
    'conservativeCollapse' => false,
],

Uses html-minifier to minify your email's HTML. You can configure the following settings for it:

minifyCSS - whether to minify the embedded CSS in your <style></style> tag

maxLineLength - set a maximum line length. Some email clients have issues with lines of code that exceed a certain amount of characters. Defaults to a conservative 500 in the production config.

preserveLineBreaks - always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Requires collapseWhitespace to be true.

collapseWhitespace - collapses white space that contributes to text nodes in a document tree (read more)

conservativeCollapse - always collapse to one space, never fully remove it

sixHex

'sixHex' => true,

Uses color-shorthand-hex-to-six-digit to ensure your HEX colour codes are written in full, with 6 digits. Some email clients don't support shorthand HEX, so we recommend leaving this enabled for production.

altText

'altText' => true,

Uses html-img-alt to make sure that all your <img> tags have an alt="" attribute defined.

If an image already includes the attribute, it'll leave it alone. If the attribute is missing, it will add an empty one.

Plaintext

'plaintext' => true,

Set this option to true, to have Maizzle generate a plaintext version for every template. The .txt file will be placed in the same directory as the HTML it's based on, and it will also have the same name.

By default, plaintext generation is enabled only in the production config.

BrowserSync

'browsersync' => [
    'tunnel' => false,
    'listing' => false,
],

Basic settings for the BrowserSync plugin, that Maizzle will use when you develop locally with npm run watch.

tunnel

This enables localhost tunneling in Browsersync (through localtunnel.me), so you can live-share a URL to an email that you're working on right now, with a colleague or a client.

Both parties see the same thing, so if you change a colour and save, it will automatically refresh the page and update on their screen as well. Scrolling is synced, too.

You can also use a string instead of a boolean - for example 'tunnel' => 'mybrand'. In this case, BrowserSync will attempt to use a custom subdomain for the URL, i.e. https://mybrand.localtunnel.me.

If that subdomain is unavailable, you will be allocated a random name as usual.

listing

When running the npm run watch command with this setting enabled, BrowserSync will open a file explorer in your browser, starting at the root of the build directory.

If you set this to false, the page opened by BrowserSync will be blank, and you'll need to manually navigate to your emails directory.

Helpers

Your config can also contain PHP helper methods that you can use to manipulate data or page variables. Maizzle comes with a 'googleFontsString' method that formats the Google Fonts names you have defined and appends them to the URL in the <link> tag.

Learn more about helper methods in the Jigsaw docs.

Jigsaw build

These are Jigsaw core settings, like output file base URL, pretty permalinks, or source and destination directories for the build process.

baseURL isn't currently used in Maizzle, so let's look at the others:

pretty

'pretty' => false,

Setting the 'pretty' key to true will have Jigsaw output each file as index.html, inside a folder named after the original source file. Maizzle disables it by default in all environments.

More on pretty permalinks, in the Jigsaw docs.

build

'build' => [
    'source' => 'source',
    'destination' => 'build_staging',
],

source defines the path to the source directory where Jigsaw should look for files to be compiled.

destination defines the path to the directory where Jigsaw should output the generated files.

Source and destination can be used with build environments

Imagine you have a folder named /spacecogs that represents a client, and it contains a bunch of emails.

You can create a config specifically for this client, and change source and destination so that when you build for this environment, Jigsaw will only build the emails for this client, instead of all emails in the /source directory:

// config.spacecogs.php

'build' => [
    'source' => 'source/spacecogs',
    'destination' => 'spacecogs',
],

Of course, you'll need to define the NPM script:

// package.json

"scripts": {
    ...
    "spacecogs": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --env=production --config=node_modules/laravel-mix/setup/webpack.config.js",
},

Tailwind

Maizzle uses Tailwind's default configuration, customised for email development.

Specifically:

Tailwind plugins 1.1.0

Starting with v1.1.0, Maizzle comes with custom Tailwind plugins.

Background gradients plugin

A plugin that generates CSS background gradients, inspired by @benface's plugin.

You can define the gradients in your tailwind.js config, just like with any other module:

let gradients = {
  'grey-dark': ['#b8c2cc', '#8795a1'],
  'red-dark': ['#e3342f', '#cc1f1a'],
  'orange-dark': ['#f6993f', '#de751f'],
  'yellow-dark': ['#ffed4a', '#f2d024'],
  'green-dark': ['#38c172', '#1f9d55'],
  'teal-dark': ['#4dc0b5', '#38a89d'],
  'blue-dark': ['#3490dc', '#2779bd'],
  'indigo-dark': ['#6574cd', '#5661b3'],
  'purple-dark': ['#9561e2', '#794acf'],
  'pink-dark': ['#f66d9b', '#eb5286'],
}

Those are the default ones Maizzle comes with, and they're based on Tailwind's default color palette. Of course, Tailwind's config() function can be used instead of hardcoding HEX values - see how.

You can add your own gradients, with as many color stops as you need:

let gradients = {
  // ...

  'hydrogen': ['#667db6', '#0082c8', '0082c8', '667db6'],
}

If you define a single color instead of an array, the resulting gradient will start from transparent and move towards the color you defined:

let gradients = {
  // ...

  'black': '#22292f',
}

... will generate classes like:

.bg-gradient-to-top-black {
  background-image: linear-gradient(to top, transparent, #22292f);
}

Of course, the generated classes cover all four directions. With the example above, you'd get:

.bg-gradient-to-top-black {
  background-image: linear-gradient(to top, transparent, #22292f);
}
.bg-gradient-to-right-black {
  background-image: linear-gradient(to right, transparent, #22292f);
}
.bg-gradient-to-bottom-black {
  background-image: linear-gradient(to bottom, transparent, #22292f);
}
.bg-gradient-to-left-black {
  background-image: linear-gradient(to left, transparent, #22292f);
}

Just like with any module, you can control which variants are generated. Maizzle only enables the hover variant by default, but you can use any of the variants, or set it to false to not generate any background gradients:

modules: {
  // ...
  gradients: ['hover'],
 // ...
},

Need inspiration? Try uigradients.com