JSX for emails
HTML emails are stuck in the past: mail clients ignore most CSS, so layouts are built from tables with inline styles. JSX components hide this mess behind tidy building blocks like <Heading>, <Button> or <Table>, and templates read like any other page.
- Bulletproof markupTables and inline styles that survive Gmail, Outlook and Apple Mail.
- Plain text for freeComponents read
this.formatand render"html"or"text"from the same template. - Async componentsThe receipt loads its order while rendering, like any other page.
Generated HTML
What the components above turn into: nested tables and inline styles, formatted with Prettier and highlighted with Prism on the server.
reset.html4.2 KB<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light" />
<title>Reset your password</title>
</head>
<body style="margin: 0; padding: 0; background-color: #f4f2fb">
<div style="display: none; max-height: 0; overflow: hidden">
Someone asked to reset your password.
</div>
<table
role="presentation"
width="100%"
cellpadding="0"
cellspacing="0"
style="background-color:#f4f2fb;font-family:-apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<tr>
<td align="center" style="padding: 32px 12px">
<table
role="presentation"
width="600"
cellpadding="0"
cellspacing="0"
style="
width: 100%;
max-width: 600px;
background-color: #ffffff;
border: 1px solid #ece9f5;
border-radius: 16px;
box-shadow: 0 12px 32px -16px rgba(76, 29, 149, 0.25);
color: #1f2937;
overflow: hidden;
">
<tr>
<td
style="
height: 6px;
line-height: 6px;
font-size: 0;
background-color: #6d28d9;
background-image: linear-gradient(120deg, #8b5cf6, #ec4899);
">
</td>
</tr>
<tr>
<td style="padding: 24px 40px 0">
<table role="presentation" cellpadding="0" cellspacing="0">
<tr>
<td
width="32"
height="32"
align="center"
style="
width: 32px;
height: 32px;
border-radius: 8px;
background-color: #6d28d9;
background-image: linear-gradient(120deg, #8b5cf6, #ec4899);
color: #ffffff;
font-size: 17px;
font-weight: 800;
">
J
</td>
<td style="padding-left: 10px; font-size: 16px; font-weight: 700">Jeasx Cloud</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding: 32px 40px 8px">
<div
style="
width: 56px;
height: 56px;
line-height: 56px;
border-radius: 16px;
background-color: #f5f3ff;
font-size: 28px;
text-align: center;
">
๐
</div>
<h1
style="margin: 20px 0 12px; font-size: 26px; line-height: 1.25; letter-spacing: -0.01em">
Reset your password
</h1>
<p style="margin: 0; font-size: 16px; line-height: 1.6; color: #6b7280">
We received a request to reset the password for ada@example.com.
</p>
</td>
</tr>
<tr>
<td style="padding: 16px 40px 0">
<table role="presentation" cellpadding="0" cellspacing="0" style="margin: 8px 0 24px">
<tr>
<td
style="
border-radius: 10px;
background-color: #6d28d9;
background-image: linear-gradient(120deg, #8b5cf6, #ec4899);
box-shadow: 0 8px 20px -8px rgba(109, 40, 217, 0.6);
">
<a
href="https://www.jeasx.dev/reset?token=example"
style="
display: inline-block;
padding: 14px 28px;
color: #ffffff;
font-size: 16px;
font-weight: 700;
text-decoration: none;
"
>Choose a new password โ</a
>
</td>
</tr>
</table>
<table
role="presentation"
width="100%"
cellpadding="0"
cellspacing="0"
style="margin: 8px 0 20px">
<tr>
<td
style="
border-left: 4px solid #8b5cf6;
border-radius: 8px;
background-color: #f5f3ff;
padding: 14px 16px;
font-size: 14px;
line-height: 1.5;
">
<span style="margin-right: 8px">โฑ</span>This link is valid for 30 minutes and can only be
used once.
</td>
</tr>
</table>
<h2
style="
margin: 8px 0 12px;
color: #6b7280;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
">
Request details
</h2>
<table
role="presentation"
width="100%"
cellpadding="0"
cellspacing="0"
style="margin-bottom: 16px">
<tr>
<td
width="120"
valign="top"
style="padding: 4px 0; font-size: 14px; line-height: 1.5; color: #6b7280">
Requested
</td>
<td style="padding: 4px 0; font-size: 14px; line-height: 1.5; font-weight: 600">
2026-11-14, 19:42 CET
</td>
</tr>
<tr>
<td
width="120"
valign="top"
style="padding: 4px 0; font-size: 14px; line-height: 1.5; color: #6b7280">
Browser
</td>
<td style="padding: 4px 0; font-size: 14px; line-height: 1.5; font-weight: 600">
Firefox on macOS
</td>
</tr>
<tr>
<td
width="120"
valign="top"
style="padding: 4px 0; font-size: 14px; line-height: 1.5; color: #6b7280">
Location
</td>
<td style="padding: 4px 0; font-size: 14px; line-height: 1.5; font-weight: 600">
Berlin, Germany
</td>
</tr>
</table>
<p style="margin: 0 0 16px; font-size: 14px; line-height: 1.6; color: #6b7280">
If you didn't ask for this, you can safely ignore this email.
</p>
</td>
</tr>
<tr>
<td style="height: 24px"></td>
</tr>
</table>
<table
role="presentation"
width="600"
cellpadding="0"
cellspacing="0"
style="width: 100%; max-width: 600px">
<tr>
<td
align="center"
style="padding: 24px 40px; color: #6b7280; font-size: 12px; line-height: 1.6">
<a href="https://www.jeasx.dev" style="color: #6b7280; text-decoration: underline"
>Help center</a
>
ยท
<a href="https://www.jeasx.dev" style="color: #6b7280; text-decoration: underline"
>Email preferences</a
><br />Sent by Jeasx Cloud for security reasons.
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>