| name | maizzle |
| description | Build responsive HTML emails using Maizzle — Tailwind CSS, modern Node, config-driven. Use when the user has chosen Maizzle, or is working in an existing Maizzle project, or wants Tailwind-based email authoring. |
Maizzle Workflow
Maizzle (https://github.com/maizzle/maizzle) is a modern email framework built on Tailwind CSS and PostCSS. Unlike Foundation/MJML it does not abstract tables with semantic tags — you write <table> directly and style with Tailwind utilities. The tradeoff: more control, modern tooling, faster builds.
Scaffolding
npx create-maizzle
cd <project>
npm install
npm run dev
Or clone a starter directly:
git clone https://github.com/maizzle/starter-default my-emails
cd my-emails && npm install
Project layout
src/
├── components/ # Reusable fragments (Nunjucks/Liquid/Handlebars syntax)
├── layouts/
│ └── main.html # Wrapper with <!DOCTYPE> boilerplate
├── templates/
│ └── *.html # Individual emails (extends layout)
└── css/
├── tailwind.css # Tailwind entrypoint
└── custom.css # Additional custom CSS
config.js # Dev config (no inlining, no minify)
config.production.js # Prod config (inline CSS, minify HTML, remove unused)
tailwind.config.js # Tailwind config (scoped to email-safe utilities)
build_production/ # Output from `npm run build`
Template skeleton
---
title: "Your subject line"
preheader: "Preview text — 80–90 chars"
---
<x-main>
<fill:template>
<table class="w-full font-sans">
<tr>
<td align="center" class="bg-slate-100 py-6">
<table class="w-[600px] bg-white">
<tr>
<td class="p-8">
<h1 class="text-2xl font-bold text-slate-900">Headline</h1>
<p class="mt-4 text-slate-700 leading-relaxed">Body copy.</p>
<table class="mt-6">
<tr>
<td class="rounded bg-blue-600 px-5 py-3">
<a href="https://example.com" class="text-white font-semibold no-underline">Call to action</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</fill:template>
</x-main>
Maizzle uses Posthtml components (<x-main>, <fill:template>) for layout composition. The layout supplies <!DOCTYPE>, <head>, and meta tags.
Tailwind config (email-scoped)
Maizzle's default tailwind.config.js extends Tailwind with email-safe values (arbitrary widths, no unsupported utilities). Customize palette/typography there:
module.exports = {
theme: {
extend: {
colors: {
brand: {
500: '#2c3e50',
600: '#1e2a38',
},
},
fontFamily: {
sans: ['Helvetica', 'Arial', 'sans-serif'],
},
},
},
}
Build commands
npm run dev
npm run build
The build runs through PostCSS → Juice (inlining) → optional Tailwind purge/content scan → output to build_production/.
Environment configs
Key Maizzle feature: separate config.js (dev) and config.production.js (prod). Typical prod flags:
module.exports = {
build: {
templates: { source: 'src/templates', destination: { path: 'build_production' } },
},
inlineCSS: true,
removeUnusedCSS: true,
shorthandCSS: true,
prettify: false,
minify: { lineLengthLimit: 500 },
}
Components
Create reusable fragments in src/components/:
<table>
<tr>
<td class="rounded bg-blue-600 px-5 py-3">
<a href="{{ href }}" class="text-white font-semibold no-underline">{{ text }}</a>
</td>
</tr>
</table>
Use with <x-button href="https://..." text="Click me" />.
Known pitfalls
- Tailwind classes not inlined →
inlineCSS: true must be set in config.production.js, not config.js.
- Unused classes bloating output → enable
removeUnusedCSS: true; verify tailwind.config.js content paths include all template/component files.
- Arbitrary values (
w-[600px]) work great and are common in email — preferred over adding custom theme values for one-offs.
- No Tailwind
@apply inside templates — use utility classes directly; @apply only in CSS files.
class attributes surviving in output → clients don't need them post-inlining; Maizzle strips by default, verify removeAttributes config.
Hand off to email-client-gotchas (required reading) and inline-and-test for preview/send.