Maizzle vs MJML: qual framework deve montar os seus e-mails?
Por Mara Levin · Atualizado em 7 de outubro de 2026 · documentação e preços conferidos nesse dia
Os dois são gratuitos e os dois transformam um código-fonte legível em HTML seguro para e-mail. Um pede que você aprenda um vocabulário novo de tags; o outro pede que você escreva componentes Vue e classes do Tailwind.
Resposta curta
Escolha o Maizzle se sua equipe já escreve Vue e Tailwind, quer condicionais e repetições dentro dos templates e gosta da ideia de um servidor de desenvolvimento que avisa sobre CSS sem suporte enquanto você digita. Escolha o MJML se os e-mails são compilados por pessoas ou serviços que não vivem no mundo JavaScript, se você prefere um vocabulário pequeno de seções e colunas prontas, ou se alguma ferramenta que você já usa aceita MJML (o Loops aceita). Licença não decide nada aqui, já que nenhum dos dois cobra.
Visão geral
| Pergunta | Maizzle | MJML |
|---|---|---|
| O que você escreve | Componentes Vue de arquivo único, estilizados com Tailwind CSS 4 | Tags no estilo XML: mj-section, mj-column, mj-text |
| Começar um projeto | npx maizzle new e depois npx maizzle serve | npm install mjml, ou o editor online |
| Compilar | npx maizzle build, ou build() / render() a partir do Node | mjml file.mjml -o dist/file.html, ou mjml2html no Node |
| Lógica no template | Vue: v-if, v-for, <script setup> | Nenhuma; tags de template vão em mj-raw e rodam numa etapa posterior |
| Componentes prontos | Mais de 30, de Button a QR codes | O conjunto padrão mais componentes da comunidade |
| Funciona fora do Node | Só build em Node | Portas e bindings para outras linguagens |
| Custo de uso | Sem planos com preço publicado | Licença MIT, segundo o FAQ do MJML |
O mesmo e-mail de boas-vindas nos dois
A documentação do Maizzle traz uma página de migração para quem vem do MJML, com o mesmo e-mail escrito das duas formas. Os dois blocos abaixo vêm dessa página: o guia do Maizzle para usuários de MJML. Ela também traz um mapa de componentes, que é um jeito rápido de ver o quanto os dois vocabulários realmente se distanciam.
MJML
<mjml>
<mj-head>
<mj-title>Welcome to Acme</mj-title>
<mj-preview>Let's get you set up.</mj-preview>
<mj-attributes>
<mj-all font-family="Helvetica, Arial, sans-serif" />
<mj-text color="#475569" font-size="16px" />
</mj-attributes>
</mj-head>
<mj-body background-color="#ffffff">
<mj-section>
<mj-column>
<mj-text font-size="24px" color="#0f172a">Hi {{ name }}</mj-text>
<mj-text>Thanks for signing up. Click below to verify your email.</mj-text>
<mj-button href="https://example.com/verify" background-color="#2563eb">
Verify email
</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml> Maizzle
<script setup>
defineProps({ name: String })
useHead({ title: 'Welcome to Acme' })
</script>
<template>
<Html>
<Head />
<Preheader>Let's get you set up.</Preheader>
<Tailwind>
<Body class="text-gray-600 text-base bg-white font-sans">
<Container class="max-w-lg">
<Text class="text-2xl text-gray-950">Hi {{ name }}</Text>
<Text>Thanks for signing up. Click below to verify your email.</Text>
<Button href="https://example.com/verify" class="bg-blue-600 text-white">
Verify email
</Button>
</Container>
</Body>
</Tailwind>
</Html>
</template> Três coisas chamam a atenção. A estilização deixa de ser atributo em cada tag e passa a ser classe do Tailwind. O cabeçalho da página é montado com useHead() e um componente Preheader, em vez de mj-title e mj-preview. E {{ name }} deixa de ser um marcador que você preenche depois: no Maizzle é uma prop do Vue, então o mesmo arquivo renderiza para qualquer nome que você passar, com toda a caixa de ferramentas do Vue (condições, repetições, valores calculados) ao redor.
Onde os dois diferem no dia a dia
Conteúdo dinâmico
O MJML não tem variáveis próprias. A documentação do MJML manda colocar a sintaxe de template dentro de mj-raw e avisa que a minificação pode tropeçar em caracteres como < nessas tags, o que se contorna com comentários htmlmin:ignore. Na prática, você compila primeiro e depois passa Handlebars, Liquid ou o seu próprio código sobre o HTML gerado. O Maizzle renderiza os componentes Vue com renderização no servidor, então a lógica roda durante o build, e o mesmo build pode entregar também uma versão em texto simples.
Trechos reutilizáveis
O MJML tem mj-include, com uma pegadinha que vale conhecer antes de adotar: os includes são ignorados em silêncio, a menos que você ative com ignoreIncludes: false no Node ou --config.allowIncludes true na linha de comando. Se o cabeçalho sumiu do HTML final, comece por aí. O equivalente no Maizzle é um componente Vue, que o guia de migração mostra como um pequeno componente Header colocado dentro do body.
import mjml2html from 'mjml'
async function compile(source) {
const { html, errors } = await mjml2html(source, { ignoreIncludes: false })
return html
} O exemplo acima segue a chamada assíncrona de mjml2html e a opção ignoreIncludes que aparecem na documentação do MJML. Quando os includes usam caminhos relativos, a mesma página da documentação também passa um filePath, para o MJML saber a partir de onde resolvê-los.
Servidor de desenvolvimento e verificações
O servidor de desenvolvimento do Maizzle tem prévia ao vivo, redimensionamento por dispositivo, emulação de modo escuro e uma aba Checks. As verificações são de dois tipos: avisos de compatibilidade montados com dados do caniemail.com e regras de lint, como um Button sem href ou uma imagem sem alt. Por padrão elas miram Gmail, Apple Mail, Outlook e Yahoo!. As ferramentas do MJML são mais enxutas: modo watch na CLI, um nível de validação (strict, soft ou skip) e plugins de editor. Nenhuma das duas substitui capturas de clientes reais, e a própria página de compatibilidade do Maizzle diz isso.
Outlook e outros clientes problemáticos
Os dois frameworks embrulham os truques de tabela e de comentário condicional para você não escrevê-los à mão. O Button do Maizzle tem props como msoPt, msoPb e msoPx para o espaçamento no Outlook clássico e um interruptor outlookFallback; há ainda os componentes Outlook, NotOutlook e OutlookBg (imagens de fundo em VML) para quando você precisa mirar esse cliente diretamente. A documentação do MJML é mais direta sobre um limite: o mj-button não é totalmente clicável em alguns clientes, por causa do suporte limitado. As duas abordagens servem; o que importa é clicar nos cantos do botão numa prévia real do Outlook.
Onde o projeto vive
O Maizzle pode ser um repositório próprio ou um plugin do Vite dentro de um app. A documentação cita Laravel, Nuxt, SvelteKit e Astro e descreve o plugin como algo que roda o Maizzle no seu próprio servidor de desenvolvimento ao lado do seu e compila os e-mails depois do vite build. O MJML fica fora do seu build: você chama a CLI ou o mjml2html onde quiser, e é por isso que ele encaixa em equipes de Rails, Django ou .NET sem nenhuma cadeia de ferramentas de front-end.
Do HTML compilado ao envio
O HTML compilado é só metade do trabalho. O Maizzle documenta receitas de deploy para Nodemailer, SendGrid, Mailgun, Postmark, Resend, AWS SES e Cloudflare. A da Resend, tirada da página de deploy, renderiza um template e o envia em poucas linhas:
import { Resend } from 'resend'
import { render } from '@maizzle/framework'
const resend = new Resend(process.env.RESEND_API_KEY)
const { html, plaintext } = await render('emails/welcome.vue')
await resend.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome',
html,
text: plaintext,
}) Para um build executado com antecedência, a forma programática é esta:
import { build } from '@maizzle/framework'
const { files } = await build({
content: ['emails/**/*.vue'],
output: { path: 'dist' },
}) O que a pilha custa em volta de dois frameworks gratuitos
O framework é a parte barata. Duas linhas da conta pesam: prévias e envio. Na página de preços, o Email on Acid lista o Basic a US$ 99 por mês com 1.000 prévias e o Premium a US$ 199 com 2.000, e o excedente custa US$ 0,15 por prévia. Cada captura de cliente ou dispositivo conta como uma prévia, então um teste em 50 clientes consome 50 delas: o Basic cobre cerca de 20 rodadas completas por mês e o Premium cerca de 40. Se você reconstrói um e-mail cinco vezes antes de enviar, essa cota acaba rápido, o que é um argumento a favor do framework com o ciclo de feedback mais curto, qualquer que seja ele.
Para o envio, a página de preços da Resend lista um plano Free a US$ 0 com 3.000 e-mails por mês (100 por dia) e o Pro a US$ 20 com 50.000. O HTML de qualquer um dos frameworks funciona com ela, e a documentação do Maizzle mostra exatamente como. Para comparar outros serviços de envio, as páginas Resend vs Postmark e Postmark vs SendGrid colocam os números lado a lado.
Escolha o Maizzle se…
- Designers e desenvolvedores já compartilham uma configuração do Tailwind e você quer que o e-mail siga a mesma.
- Os templates precisam de lógica de verdade: troca de idioma, linhas repetidas a partir de dados, blocos opcionais.
- Você quer que o framework avise sobre CSS sem suporte antes de abrir um serviço de prévias.
- Os e-mails ficam junto de um app Vite (Laravel, Nuxt, SvelteKit, Astro) e compartilham componentes com ele.
Escolha o MJML se…
- O seu backend não é JavaScript, ou vários serviços precisam compilar o mesmo código-fonte.
- Você prefere um vocabulário curto em que o layout é
mj-sectionemj-columne não quer pensar em Tailwind. - Uma plataforma que você usa aceita MJML direto. O Loops, por exemplo, permite subir o seu próprio MJML no lugar do editor dele.
- Pessoas que não são desenvolvedoras de front-end precisam ler e revisar os templates.
Passando de um para o outro
Ir do MJML para o Maizzle é a direção mais bem documentada, já que o Maizzle fornece o mapa de componentes. Reconstrua primeiro um e-mail de baixo risco, como a redefinição de senha, envie as duas versões pelas mesmas prévias de clientes e compare as capturas. Ir no sentido oposto significa achatar a lógica do Vue em marcadores, então decida desde já onde os blocos condicionais vão morar depois. Para outras combinações, veja MJML vs React Email e React Email vs Maizzle; e, para os limites de CSS por trás de tudo isso, leia CSS em e-mail e compatibilidade entre clientes.
Perguntas frequentes
O Maizzle ainda é "tabelas HTML com Tailwind"?
Não na documentação atual. O Maizzle se apresenta como um framework para montar e-mails HTML com Vue e Tailwind CSS, os templates são componentes Vue de arquivo único e a documentação está versionada como 6.x. Tutoriais antigos que mostram tabelas escritas à mão com classes utilitárias descrevem um fluxo anterior, então confira para qual versão o tutorial foi escrito antes de copiar o código.
Dá para migrar uma biblioteca MJML existente para o Maizzle?
Não existe conversor de um clique, mas o Maizzle publica um mapa de componentes para isso. mj-section vira Section, mj-column vira Column, mj-button vira Button, mj-preview vira Preheader e mj-include vira um componente Vue próprio. Comece pelos e-mails com menos atributos personalizados e compare as prévias nos clientes antes de levar o resto.
Qual dos dois exige menos configuração para uma equipe que não usa Node?
O MJML. A documentação dele lista portas e bindings para outras linguagens, e dá para compilar uma vez na integração contínua e entregar o HTML a um backend escrito em qualquer coisa. O Maizzle pressupõe um build em Node com Vue, seja como projeto próprio ou como plugin do Vite dentro de um app existente.
Algum dos dois testa meus e-mails em clientes reais?
Não. O Maizzle roda verificações de compatibilidade e de lint no servidor de desenvolvimento com dados do caniemail.com e recomenda fazer testes de renderização em clientes reais antes do envio. O MJML valida a marcação pelas próprias regras. Para capturas de tela de clientes de verdade, ainda é preciso um serviço de prévias como Email on Acid ou Litmus.