Maizzle é uma estrutura que ajuda você a criar rapidamente e-mails em HTML com Tailwind CSS e pós-processamento avançado específico para e-mails.
Recomendo a leitura da documentação em maizzle.com.
Instalação
npm install tailwindcss-box-shadow@"^2.0.3" \
tailwindcss-email-variants@"^3.0.1" \
tailwindcss-mso@"^1.4.3" \
tailwindcss-preset-email@"^1.1.0" \
@maizzle/framework@"latest" \
autoprefixer@"^10.4.20"
Configuração
Crie maizzle.config.local.cjs
na raiz do projeto com o conteúdo abaixo:
/*
|-------------------------------------------------------------------------------
| Development config maizzle.config.local.cjs https://maizzle.com/docs/environments
|-------------------------------------------------------------------------------
|
| The exported object contains the default Maizzle settings for development.
| This is used when you run `maizzle build` or `maizzle serve` and it has
| the fastest build time, since most transformations are disabled.
|
*/
/** @type {import("@maizzle/framework").Config} */
module.exports = {
locals: {
assetPath: "static/emails",
page: {
language: "pt_BR"
},
app: {
name: "Maizzle",
url: "https://maizzle.com"
}
},
build: {
posthtml: {
expressions: {
delimiters: ["[[", "]]"],
unescapeDelimiters: ["[[[", "]]]"]
}
},
browsersync: {
watch: ["resources/maizzle/**/*.*", "tailwind.maizzle.js"]
},
tailwind: {
config: "tailwind.maizzle.js",
css: "resources/maizzle/css/tailwind.css"
},
templates: {
source: "resources/maizzle/templates",
filetypes: ["html", "blade.php"],
destination: {
path: "build"
},
assets: {
source: "resources/maizzle/images",
destination: "images"
}
},
layouts: {
root: "resources/maizzle/layouts"
},
components: {
root: "resources/maizzle/",
folders: ["components", "layouts", "templates"]
},
fail: "verbose"
},
prettify: true
};
Crie maizzle.config.production.cjs
na raiz do projeto com o conteúdo abaixo:
/*
|-------------------------------------------------------------------------------
| Production config maizzle.config.production.cjs https://maizzle.com/docs/environments
|-------------------------------------------------------------------------------
|
| This is where you define settings that optimize your emails for production.
| These will be merged on top of the base config.js, so you only need to
| specify the options that are changing.
|
*/
/** @type {import("@maizzle/framework").Config} */
module.exports = {
locals: {
assetPath: "static/emails",
page: {
language: "pt_BR"
},
app: {
name: "Maizzle",
url: "https://maizzle.com"
}
},
build: {
posthtml: {
expressions: {
delimiters: ['[[', ']]'],
unescapeDelimiters: ['[[[', ']]]']
}
},
tailwind: {
config: "tailwind.maizzle.js",
css: "resources/maizzle/css/tailwind.css"
},
templates: {
source: "resources/maizzle/templates",
filetypes: ["html", "blade.php"],
destination: {
path: "resources/views/emails",
extension: "blade.php"
},
assets: {
source: "resources/maizzle/images",
destination: "../../static/emails"
}
},
layouts: {
root: "resources/maizzle/layouts"
},
components: {
root: "resources/maizzle/",
folders: ["components", "layouts", "templates"]
},
fail: "verbose"
},
inlineCSS: true,
removeUnusedCSS: true,
shorthandCSS: true,
minify: true,
events: {
afterBuild(files, config) {
console.log(files);
}
}
};
Crie tailwind.maizzle.js
na raiz do projeto com o conteúdo abaixo:
/** @type {import("tailwindcss").Config} */
// tailwind.maizzle.js
export default {
content: [
"./resources/maizzle/components/**/*.{html,blade.php}",
"./resources/maizzle/layouts/**/*.{html,blade.php}",
"./resources/maizzle/templates/**/*.{html,blade.php}",
],
theme: {
screens: {
sm: { max: "600px" },
xs: { max: "425px" },
},
extend: {
spacing: {
screen: "100vw",
full: "100%",
0: "0",
0.5: "2px",
1: "4px",
1.5: "6px",
2: "8px",
2.5: "10px",
3: "12px",
3.5: "14px",
4: "16px",
4.5: "18px",
5: "20px",
5.5: "22px",
6: "24px",
6.5: "26px",
7: "28px",
7.5: "30px",
8: "32px",
8.5: "34px",
9: "36px",
9.5: "38px",
10: "40px",
11: "44px",
12: "48px",
14: "56px",
16: "64px",
20: "80px",
24: "96px",
28: "112px",
32: "128px",
36: "144px",
40: "160px",
44: "176px",
48: "192px",
52: "208px",
56: "224px",
60: "240px",
64: "256px",
72: "288px",
80: "320px",
96: "384px",
},
borderRadius: {
none: "0px",
sm: "2px",
DEFAULT: "4px",
md: "6px",
lg: "8px",
xl: "12px",
"2xl": "16px",
"3xl": "24px",
},
boxShadow: {
sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
DEFAULT:
"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)",
md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
"2xl": "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
inner: "inset 0 2px 4px 0 rgba(0, 0, 0, 0.05)",
},
fontFamily: {
sans: [
"ui-sans-serif",
"system-ui",
"-apple-system",
'"Segoe UI"',
"sans-serif",
],
serif: [
"ui-serif",
"Georgia",
"Cambria",
'"Times New Roman"',
"Times",
"serif",
],
mono: ["ui-monospace", "Menlo", "Consolas", "monospace"],
},
fontSize: {
0: "0",
xxs: "11px",
xs: "12px",
"2xs": "13px",
sm: "14px",
"2sm": "15px",
base: "16px",
lg: "18px",
xl: "20px",
"2xl": "24px",
"3xl": "30px",
"4xl": "36px",
"5xl": "48px",
"6xl": "60px",
"7xl": "72px",
"8xl": "96px",
"9xl": "128px",
},
letterSpacing: (theme) => ({
...theme("width"),
}),
lineHeight: (theme) => ({
...theme("width"),
}),
maxWidth: (theme) => ({
...theme("width"),
xs: "160px",
sm: "192px",
md: "224px",
lg: "256px",
xl: "288px",
"2xl": "336px",
"3xl": "384px",
"4xl": "448px",
"5xl": "512px",
"6xl": "576px",
"7xl": "640px",
}),
minHeight: (theme) => ({
...theme("width"),
}),
minWidth: (theme) => ({
...theme("width"),
}),
},
},
corePlugins: {
preflight: false,
backgroundOpacity: false,
borderOpacity: false,
divideOpacity: false,
placeholderOpacity: false,
textOpacity: false,
},
plugins: [
require("autoprefixer")(),
require("tailwindcss-mso"),
require("tailwindcss-box-shadow"),
require("tailwindcss-email-variants"),
],
presets: [require("tailwindcss-preset-email")],
};
Copie o conteúdo de src/
que pode ser encontrado no repositório oficial para resources/maizzle
.
Altere o package.json
para :
"scripts":{
...
"mail": "maizzle serve",
"mail:build": "maizzle build production"
}
Altere os conteúdos das pastas components
, layouts
, templates
para usar [[ ]]
e [[[ ]]]
ao invés de {{ }}
e {{{ }}}
, pois a configuração permite usar as diretivas do blade sem usar @{{}}
.
# find resources/maizzle -type f: Encontra todos os arquivos dentro do diretório resources/maizzle
# -exec sed -i 's/{{{/[[[/g; s/}}}/]]]/g; s/{{/[[/g; s/}}/]]/g' {} \;: Para cada arquivo encontrado, o comando sed faz as substituições.
find resources/maizzle -type f -exec sed -i 's/{{{/[[[/g; s/}}}/]]]/g; s/{{/[[/g; s/}}/]]/g' {} \;
Altere o nome dos arquivos em components
, layouts
, templates
para terminarem com blade.php
, isso ajudará o seu IDE a identificar as diretivas blade.
# find resources/maizzle -type f -name "*.html": Encontra todos os arquivos que terminam com .html no diretório resources/maizzle.
# -exec bash -c 'mv "$0" "${0%.html}.blade.php"' {}: Para cada arquivo encontrado, o comando mv renomeia o arquivo removendo a extensão .html e adicionando .blade.php.
find resources/maizzle -type f -name "*.html" -exec bash -c 'mv "$0" "${0%.html}.blade.php"' {} \;
Uso
php artisan make:mail OrderShipped
<?php
namespace App\Mail;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(
public Order $order,
) {}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.welcome',
with: [
'orderName' => $this->order->name,
],
);
}
}
Um exemplo de template resources/maizzle/templates/welcome.blade.php
<x-main>
<div class="bg-slate-50 font-sans sm:px-4">
<table align="center">
<tr>
<td class="w-[552px] max-w-full">
<div class="my-12 text-center sm:my-8">
<a href="https://maizzle.com">
<img
src="{{ asset("/static/logo.svg") }}"
width="70"
alt="Maizzle"
/>
</a>
</div>
<table class="w-full">
<tr>
<td class="rounded bg-white p-12 text-base text-slate-700 shadow-sm sm:px-6" >
<h1 class="m-0 mb-6 text-2xl font-semibold text-black sm:leading-8" >
Hello, {{ $orderName }}
</h1>
<p class="m-0 leading-6">
Is it you we're looking for?
<br />
<br />
Please confirm your email address by
clicking the button below:
</p>
<x-spacer height="24px" />
<x-button href="https://maizzle.com">
Confirm email address →
</x-button>
<x-divider
space-y="32px"
class="bg-slate-200"
/>
<p class="m-0">
If you didn't sign up for Maizzle, you can
safely ignore this email.
<br />
<br />
Thanks,
<br />
The Maizzle Team
</p>
</td>
</tr>
<tr role="separator">
<td class="leading-12">‍</td>
</tr>
<tr>
<td class="px-6 text-center text-xs text-slate-600">
<p class="m-0 mb-4 uppercase">
Powered by Maizzle
</p>
<p class="m-0 italic">
Quickly build HTML emails with Tailwind CSS
</p>
<p class="cursor-default">
<a
href="https://maizzle.com/docs/"
class="text-indigo-700 [text-decoration:none] hover:![text-decoration:underline]"
>
Docs
</a>
•
<a
href="https://github.com/maizzle"
class="text-indigo-700 [text-decoration:none] hover:![text-decoration:underline]"
>
Github
</a>
•
<a
href="https://twitter.com/maizzlejs"
class="text-indigo-700 [text-decoration:none] hover:![text-decoration:underline]"
>
Twitter
</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</x-main>
Rode o comando abaixo para gerar o arquivo blade final.
npm run mail:build
Top comments (0)