Skip to content

feat: maizzle 6 - #1708

Merged
cossssmin merged 460 commits into
masterfrom
next
Jun 4, 2026
Merged

feat: maizzle 6#1708
cossssmin merged 460 commits into
masterfrom
next

Conversation

@cossssmin

@cossssmin cossssmin commented Apr 4, 2026

Copy link
Copy Markdown
Member

Maizzle 6

Holy crap it's finally here! Tailwind CSS 4, Vue templating, Vite plugin and lots more 🥳

Maizzle 6 is a complete framework rewrite. It uses Vite for the build system and dev server, and it can even be used as a Vite plugin in your existing vite.config.js. We've moved to using Vue for templating: not only do you get a much better DX when coding emails, but the vast Vue ecosystem means you can do a lot more things, and LLMs will now be better at using Maizzle.

Given the above, this version is not backwards-compatible with Maizzle 5.

Highlights

  • Vite build system and dev server
  • Maizzle as a Vite plugin
  • Vue templating with SFCs
  • Tailwind CSS 4
  • Revamped dev UI
  • 30+ built-in components
  • Composables for per-template configuration
  • AI skills for LLMs

Upgrade guide: SOON

Getting started

Scaffold a new project:

npx maizzle new

When prompted, select the Default starter.

Or use it as a Vite plugin in an existing project:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import { maizzle } from '@maizzle/framework'

export default defineConfig({
  plugins: [
    vue(),
    tailwindcss(),
    maizzle({
      root: 'resources/js/emails',
      output: {
        path: 'resources/views/emails',
        extension: 'blade.php',
      },
      static: {
        source: ['resources/js/emails/images'],
      },
    }),
  ],
})

Laravel

Maizzle 6 detects Laravel projects and auto-configures itself.

Components

Maizzle 6 ships with a generous set of built-in Vue components that you can use without importing.

Skeleton

  • <Html>
  • <Head>
  • <Body>
  • <Layout>
  • <Tailwind>

Layout

  • <Container>
  • <Section>
  • <Row>
  • <Column>
  • <Overlap>
  • <Spacer>
  • <Hr>

Use Tailwind utilities directly on any of these. Widths, padding and Outlook fallbacks are computed for you:

<template>
  <Container class="max-w-xl">
    <Section>
      <Row>
        <Column>1</Column>
        <Column>2</Column>
      </Row>
    </Section>
  </Container>
</template>

You can opt out of Outlook fallback markup with :outlook-fallback="false" on any of these (cascades to nested components).

Content

  • <Heading>
  • <Text>
  • <Link>
  • <Button>
  • <Img>
  • <Font>
  • <Preheader>
  • <Markdown>
  • <CodeBlock> and <CodeInline>
  • <QrCode>

Conditional / utility

  • <Outlook> and <NotOutlook>
  • <NoWidows>
  • <OutlookBg>
  • <Vml>
  • <WithUrl>
  • <Raw>

Plaintext

Dedicated plaintext components, plus usePlaintext(options) composable for per-template configuration.

Composables

Available inside any <script setup>:

  • defineConfig()
  • useDoctype()
  • usePlaintext()
  • usePreheader()
  • useBaseUrl() — set url.base per template
  • useUrlQuery() — set url.query per template
  • useTransformers() — toggle the transformer pipeline per template (booleans or granular object)
  • useCurrentTemplate()
  • useEvent() — register events from inside .vue and .md templates

Dev UI

Completely revamped local dev experience.

Test emails

A Test tab at the bottom of the UI sends actual test emails via Nodemailer. Configure server.email, or leave it unset to fall back to Ethereal for preview links.

Checks (Compatibility + Linter)

Compatibility and linter unified into a single Checks tab. Define which clients to check against, or disable entirely:

export default defineConfig({
  server: {
    checks: {
      clients: ['outlook', 'gmail'],
    },
  },
})

Jump-to-editor 🔥

Click any error/warning to open the component or template in your default editor, cursor at the exact line.

Dark mode emulator

Toggle from the command dialog to approximate how email clients auto-invert your colors.

Command palette

  • Ctrl/Cmd + K (or /) to open
  • Email search matches parent directory names (app/welcomeap w)
  • Order-independent token search (welcome app == app welcome)
  • Result count in footer
  • Quick links to docs, Can I Email, copy code, etc.

Device viewport

Width × height indicators are number inputs — type or scroll to change values. Click × to reset.

QR code

maizzle serve --host prints a QR code for the network URL, scan from your phone instantly.

Misc

  • Auto-imports new components added while the dev server is running
  • Source previews prefetched in the background (instant tab switching)
  • Custom scrollbars, polished resizables, touch drag support, mobile menu

Configuration

CSS

  • css.inline defaults to true
  • css.purge defaults to true
  • css.shorthand defaults to true
  • html.format defaults to true
  • <style raw> skips Tailwind/Lightning CSS compilation
  • <style embed> skips inlining

Build API

The programmatic build() API now takes config directly:

await build({ css: { inline: true } })
await build('./my.config.ts')
await build() // loads maizzle.config.ts from cwd

Markdown layouts

.md templates are wrapped in a built-in MarkdownLayout automatically. Choose a different layout via frontmatter:

---
layout: Layout
title: Welcome
---

# Hello!

Set layout: false to opt out.

Other

  • maizzle prepare postinstall script generates .maizzle/*.d.ts so your editor knows about composables and components before the dev server starts
  • vue.plugins accepts a factory form
  • Liquid-like filters via attributes
  • Auto self-closing tags (<br><br /> based on doctype)
  • Six-hex color transformer (#fff#ffffff)
  • AMP4Email support

AI / Skills

Bundled Maizzle skill for LLMs, plus:

  • Skill for converting React Email components to Maizzle
  • Skill for converting MJML to Maizzle
  • V5 → V6 migration reference

Requirements

Maizzle 6 requires Node.js 22+


Full diff: v5.5.0...v6.0.0

@cossssmin cossssmin changed the title feat: add tailwindcss v4 support feat: maizzle 6 Apr 4, 2026
cossssmin and others added 28 commits April 23, 2026 13:06
too many issues with remote content, just use your os' screenshotting functionality...
use caniemail data directly, drop outdated caniemail package, improve signal to noise in results
use <style raw> to have the contents skip our tailwind pipeline
choose which clients or completely turn it off
rough approximation of how email clients auto-invert colors for their "dark mode"
ctrl+b was firing twice, so there was no value changed in fact
derive mso width from tailwind utilities or inline css
derive mso width from tailwind utilities or inline css
make it also work with just tailwind utilities or inline css width on wrappers
`let counter = 0` in `<script setup>` is compiled into the component's setup function, so it reset on every instance. Container/Section/Column/Overlap all minted `c1`/`s1`/`co1`/`o1` for every render, causing marker IDs to collide. Two `<Container>`s on a page resolved to the same MSO width, etc. Move the counter into a shared `nextId(prefix)` helper in utils.ts where it lives at true module scope.
Co-authored-by: Copilot <copilot@github.com>
cossssmin added 29 commits June 4, 2026 15:36
@cossssmin
cossssmin merged commit f6f5f6c into master Jun 4, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant