better-svelte-email Svelte Themes

Better Svelte Email

๐Ÿ“ง Render emails in Svelte effortlessly with first-class tailwind support

Better Svelte Email

Create beautiful emails in Svelte with first-class Tailwind support

Website ยท GitHub

Tests npm version GitHub stars

Features

  • Stable & Future-Proof - Uses Svelte's public preprocessor API
  • Tailwind CSS Support - Transforms Tailwind classes to inline styles for email clients
  • Built-in Email Preview - Visual email preview and test sending
  • TypeScript First - Fully typed with comprehensive type definitions
  • Well Tested - Extensive test coverage with unit and integration tests

See Roadmap for future features and planned improvements.

Why?

Existing Svelte email solutions have significant limitations:

  • svelte-email hasn't been updated in over 2 years
  • svelte-email-tailwind suffers from stability issues and maintaining it is not sustainable anymore

Better Svelte Email is a complete rewrite built on Svelte's official preprocessor API, providing the rock-solid foundation your email infrastructure needs. It brings the simplicity, reliability, and feature richness of React Email to the Svelte ecosystem.

Quick Start

1. Install the package

npm i -D better-svelte-email
# or
bun add -D better-svelte-email
# or
pnpm add -D better-svelte-email

2. Configure the Preprocessor

Add the preprocessor to your svelte.config.js:

import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { betterSvelteEmailPreprocessor } from 'better-svelte-email';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    preprocess: [vitePreprocess(), betterSvelteEmailPreprocessor()],
    kit: {
        adapter: adapter()
    }
};

export default config;

3. Create Email Components

Create your email templates in src/lib/emails/:

<!-- src/lib/emails/welcome.svelte -->
<script>
    import { Html, Head, Body, Preview, Container, Text, Button } from 'better-svelte-email';

    let { name = 'User' } = $props();
</script>

<Html>
    <Head />
    <Body class="bg-gray-100">
        <Preview preview="Welcome Email" />
        <Container class="mx-auto p-8">
            <Text class="mb-4 text-2xl font-bold">
                Welcome, {name}!
            </Text>

            <Button
                href="https://example.com"
                class="rounded bg-orange-600 px-6 py-3 text-white sm:text-sm"
            >
                Get Started
            </Button>
        </Container>
    </Body>
</Html>

4. Render and Send

// src/routes/api/send-email/+server.ts
import { render } from 'svelte/server';
import WelcomeEmail from '$lib/emails/welcome.svelte';

export async function POST({ request }) {
    const { name, email } = await request.json();

    // Render email (preprocessor already ran at build time!)
    const result = render(WelcomeEmail, { props: { name } });

    // Send email using your preferred service (Resend, SendGrid, etc.)
    // await resend.emails.send({
    //   from: '[email protected]',
    //   to: email,
    //   subject: 'Welcome!',
    //   html: result.body
    // });

    return new Response('Sent');
}

Email Preview Component

Better Svelte Email includes a built-in preview component for visually developing and testing your email templates during development.

Setup

Create a preview route in your SvelteKit app:

<!-- src/routes/preview/+page.svelte -->
<script lang="ts">
    import { EmailPreview } from 'better-svelte-email/preview';

    let { data } = $props();
</script>

<EmailPreview emailList={data.emails} />
// src/routes/preview/+page.server.ts
import { emailList, createEmail, sendEmail } from 'better-svelte-email/preview';
import { env } from '$env/dynamic/private';

export function load() {
    const emails = emailList({
        path: '/src/lib/emails' // optional, defaults to '/src/lib/emails'
    });

    return { emails };
}

export const actions = {
    ...createEmail,
    ...sendEmail({ resendApiKey: env.RESEND_API_KEY })
};

Features

  • HTML Source View - Inspect the generated HTML with syntax highlighting
  • Copy to Clipboard - Quickly copy the rendered HTML
  • Test Email Sending - Send test emails directly from the preview UI using Resend
  • Template List - Browse all your email templates in one place

Environment Variables

To enable test email sending, add your Resend API key to your .env file:

RESEND_API_KEY=re_your_api_key_here

Get your API key from Resend.

Custom Email Provider

If you prefer to use a different email provider, you can pass a custom send function:

export const actions = {
    ...createEmail,
    ...sendEmail({
        customSendEmailFunction: async ({ from, to, subject, html }) => {
            // Use your preferred email service (SendGrid, Mailgun, etc.)
            try {
                await yourEmailService.send({ from, to, subject, html });
                return { success: true };
            } catch (error) {
                return { success: false, error };
            }
        }
    })
};

Configuration

Here are the available options:

betterSvelteEmailPreprocessor({
    pathToEmailFolder: '/src/lib/emails',
    debug: false,
    tailwindConfig: {
        theme: {
            extend: {
                colors: {
                    brand: '#FF3E00'
                }
            }
        }
    }
});

Minimum Svelte Version

The minimum supported Svelte version is 5.14.3. For older versions, you can use svelte-email-tailwind.

Supported Features

โœ… Supported

  • โœ… Static Tailwind classes
  • โœ… Custom Tailwind classes (bg-[#fff], my:[40px], ...)
  • โœ… All standard Tailwind (v3) utilities (colors, spacing, typography, etc.)
  • โœ… Responsive breakpoints (sm:, md:, lg:, xl:, 2xl:)
  • โœ… HTML elements and Svelte components
  • โœ… Nested components
  • โœ… Conditional blocks ({#if})
  • โœ… Each blocks ({#each})
  • โœ… Custom Tailwind configurations

โŒ Not Supported (Yet) (See Roadmap)

  • โŒ Tailwind v4
  • โŒ CSS Object (style={{ color: 'red' }})
  • โŒ Dynamic class expressions (class={someVar})
  • โŒ Arbitrary values in responsive classes (sm:[color:red])
  • โŒ Container queries

Author

Anatole Dufour (@Konixy)

Development

Running Tests

bun run test

All tests must pass before pushing to main. The CI/CD pipeline will automatically run tests on every push and pull request.

Building

bun run build

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

To do so, you'll need to:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/amazing-feature)
  3. Make your changes
  4. Run tests (bun run test)
  5. Commit your changes using conventional commits:
    • feat: - New features
    • fix: - Bug fixes
    • docs: - Documentation changes
    • test: - Test additions/changes
    • chore: - Maintenance tasks
  6. Push to your branch (git push origin feat/amazing-feature)
  7. Open a Pull Request

Acknowledgements

Many components and logic were inspired by or adapted from svelte-email-tailwind and react-email. Huge thanks to the authors and contributors of these projects for their excellent work.

Top categories

Loading Svelte Themes