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ê escreveComponentes Vue de arquivo único, estilizados com Tailwind CSS 4Tags no estilo XML: mj-section, mj-column, mj-text
Começar um projetonpx maizzle new e depois npx maizzle servenpm install mjml, ou o editor online
Compilarnpx maizzle build, ou build() / render() a partir do Nodemjml file.mjml -o dist/file.html, ou mjml2html no Node
Lógica no templateVue: v-if, v-for, <script setup>Nenhuma; tags de template vão em mj-raw e rodam numa etapa posterior
Componentes prontosMais de 30, de Button a QR codesO conjunto padrão mais componentes da comunidade
Funciona fora do NodeSó build em NodePortas e bindings para outras linguagens
Custo de usoSem planos com preço publicadoLicenç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.

Página de preços da Resend, captura de out. 2026
Página de preços da Resend em 7 de out. de 2026. Fonte: https://resend.com/pricing

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-section e mj-column e 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.