Developer Tools

Svelte Email

better-svelte-email renders Svelte 5 components to email HTML. The original svelte-email is abandoned. Example, limits and release status.

Olivier Bazoud
November 5, 2026
8 min read

better-svelte-email is a library for writing an email as a Svelte 5 component and rendering it to an HTML string. You build the message from its components (Html, Body, Container, Section, Text, Button and others), style it with Tailwind v4 or plain CSS, and call a Renderer. The older package named svelte-email is abandoned, so install better-svelte-email.

At a glance
Language
TypeScript, Svelte 5
License
MIT, free
Maintainer
Anatole Dufour
Latest release
2.3.0 (2026-08-29)
Weekly npm downloads
18,935

Figures read on November 5, 2026.

Good fit
  • A SvelteKit or Svelte 5 team that wants components for emails
  • Tailwind v4 classes, or plain CSS
  • Any sending provider: render needs no account
  • A SvelteKit or Vite SSR build that renders the email on the server
Not a fit
  • A Svelte app older than 5.14.3
  • A backend outside JavaScript

Minimal example

This is condensed from the project's getting-started page. The email is a Svelte component.

svelte
<!-- src/lib/emails/welcome.svelte -->
<script>
import { Html, Head, Body, Container, Section, Text, Button } from '@better-svelte-email/components';
let { name = 'there' } = $props();
</script>
<Html>
<Head />
<Body class="bg-zinc-100">
<Container class="m-8 mx-auto max-w-lg rounded-2xl bg-white p-8">
<Section class="mx-auto text-center">
<Text class="text-2xl font-bold text-zinc-900">Welcome {name}!</Text>
<Button href="https://example.com/docs" pX={24} pY={14} class="rounded-lg bg-orange-600 text-white">
Explore the docs
</Button>
</Section>
</Container>
</Body>
</Html>

Render it on the server:

TypeScript
import { Renderer } from '@better-svelte-email/server';
import WelcomeEmail from '$lib/emails/welcome.svelte';
const { render } = new Renderer();
const html = await render(WelcomeEmail, { props: { name: 'Jane' } });

Install @better-svelte-email/components and @better-svelte-email/server. The project docs require svelte 5.14.3 or later, and Tailwind 4 or later if you use Tailwind classes.

Pros and cons

Pros
  • Built for Svelte 5
  • Tailwind v4 classes, not every utility
  • Outlook conditionals on Button
  • Plain-text version with toPlainText
  • Live-reload preview CLI
Cons
  • Single maintainer
  • Packages renamed in v2
  • Thin Outlook on Windows support
  • Tailwind v4 output not downleveled
  • Needs a Svelte-aware build

The details behind each point are in Limits and gotchas and Maintenance.

How it works

The layout components emit tables. Section renders a <table> with role="presentation", a tbody, tr and td, and Html writes an XHTML 1.0 Transitional doctype. The Button component emits <!--[if mso]> blocks for Outlook.

The server package compiles your Tailwind classes and inlines the plain rules into style attributes. Breakpoints, hover:, dark: and space-y-* go to a <style> block in the head instead. It also parses and inlines its own customCSS option, adds the media queries responsive breakpoints need to the head, and leaves class attributes alone if you set disableTailwind. It depends on postcss and tailwindcss, not on a general-purpose inliner such as juice.

toPlainText produces a text version of the rendered HTML, and npx @better-svelte-email/cli dev serves a live-reload preview of your emails.

The output is the HTML that becomes the body of a MIME message. MIME and the message format explain what travels on the wire.

Send it with an email API

render returns a string. Pass it as html to the Nuntly SDK.

TypeScript
import { Nuntly } from '@nuntly/sdk';
import { Renderer } from '@better-svelte-email/server';
import WelcomeEmail from '$lib/emails/welcome.svelte';
const nuntly = new Nuntly({ apiKey: process.env.NUNTLY_API_KEY! });
const { render } = new Renderer();
const html = await render(WelcomeEmail, { props: { name: 'Jane' } });
await nuntly.emails.send({
from: 'Acme <hello@example.com>',
to: 'jane@example.org',
subject: 'Welcome to Acme',
html,
});

The Send Your First Email guide covers the client setup and the same call for plain text.

Email client support

Claimed by the project
  • All Tailwind v4 utilities
  • Outlook conditionals on Button
  • Parity with React Email
Not published
  • List of supported email clients
  • Outlook support level
  • Gmail behavior
  • Dated test results

The claims come from the README, which says the library brings "the simplicity, reliability, and feature richness of React Email to the Svelte ecosystem". It names no client, and we did not test the output in any.

Outlook on Windows is the weak spot. Only Button carries Outlook code, and Row and Column emit no ghost table. Gmail does not support @media (hover) or prefers-color-scheme according to caniemail, so hover: and dark: classes will not apply there, and gradient utilities render no background at all. Before you ship, send a test from your own template to Outlook on Windows and Gmail, and check each CSS property you depend on in caniemail.

Limits and gotchas

  • Outlook on Windows support is thin. Only Button carries Outlook code, and its spacers are sized from the pX and pY props, so padding set with Tailwind classes does not reach Outlook. Row and Column emit no ghost table, and Svelte strips a hand-written <!--[if mso]> comment, so emit your own conditionals through {@html '...'}.
  • Tailwind v4 output is not downleveled. Breakpoints stay as @media (width >= 40rem) and hover: is wrapped in @media (hover: hover), which Gmail does not support per caniemail. Gradient utilities leave no background, and bg-black/50 is flattened against white into a solid gray, so treat responsive and hover classes as enhancements and set solid colors yourself.
  • Some docs examples do not match the code. The Getting started sample puts Button directly in Row, and the parser moves the links out of the table, so wrap each one in a Column. Heading is documented with a default of h1, but without the as prop it renders nothing.
  • Installs and builds break in a few known ways. Older tutorials import from better-svelte-email or install the preview package, and v2 moved everything to the @better-svelte-email/* scope. @better-svelte-email/components 2.3.0 ships a directory import that Node's ESM rejects unless you bundle it, Vite may need ssr.noExternal for nanoid or postcss, and Cloudflare Workers with Vite 8 fails with no fix.
  • The preview is not your production renderer. npx @better-svelte-email/cli dev ignores svelte.config.js, never sees a tailwindConfig you pass in code, loads src/app.css on its own, and adds a sans-serif body font the sent email does not have. If that stylesheet defines a class-based dark variant (shadcn style), dark: classes never apply in the email, so pass the CSS you ship with -c and check a real send.

Maintenance

Active: five releases since 2.0.0 on 2026-04-27, the latest 2.3.0 on 2026-08-29, with a commit on the same day.

  • Install @better-svelte-email/components and @better-svelte-email/server. Version 2 moved everything to this scope, so older tutorials that import better-svelte-email are outdated, and @better-svelte-email/preview is deprecated.
  • Do not install the original svelte-email. It is abandoned, with no release since 2023 and a Svelte 3 peer dependency, yet it still gets about 21,000 downloads a week.

Compare

Sibling tools in this catalog:

  • React Email: React components, the model better-svelte-email borrows from.
  • JSX Email: React components with its own maintainer.
  • MJML: MJML markup instead of components.
  • mjml-react: React components compiled through MJML.
  • Maizzle: Vue components with Tailwind CSS.
  • @unitpost/email: JSX or a string, with Tailwind-style classes.

The email frameworks hub lists every tool with its status.

FAQ

Is svelte-email still maintained?

No. The last npm release of svelte-email is 0.0.4 on 2023-02-09 and the last default-branch commit is from 2023-06-14 (read 2026-11-05). Its issue about Svelte 5 has been open since 2024-02-25. The repository is not archived, and the package still gets about 21,000 downloads a week.

What replaces svelte-email for Svelte 5?

better-svelte-email by Anatole Dufour. It is a rewrite of svelte-email-tailwind inspired by React Email, it needs Svelte 5.14.3 or later, and its latest release is 2.3.0 on 2026-08-29 (read 2026-11-05). Install @better-svelte-email/components and @better-svelte-email/server.

Does better-svelte-email support Tailwind?

Yes, Tailwind v4. The server package compiles Tailwind classes and inlines them into style attributes. Tailwind is optional: plain CSS works, and disableTailwind leaves class attributes untouched.

Do I need Resend to use better-svelte-email?

No. The renderer returns an HTML string and needs no account. Only the CLI preview's test send uses a Resend API key. In your app you pass the string to whatever sending service or SMTP client you use.

Can I use svelte-email with SvelteKit and Svelte 5?

Not reliably. The original targets Svelte 3 and Component.render(...) breaks on Svelte 5. There are Svelte 5 forks, but svelty-email is archived and @sveltelaunch/svelte-5-email has had no push since 2024-06-01 (read 2026-11-05). Use better-svelte-email instead.