Skip to main content

Overview

This guide will walk you through creating, rendering, and sending your first email with Better Svelte Email. By the end, you’ll have a working welcome email that looks great across all email clients.
1

Create Your First Email Component

Create a new file for your welcome email component. We’ll use Tailwind CSS for styling, but bare CSS works too.
<script>
  import {
    Html,
    Head,
    Body,
    Preview,
    Container,
    Section,
    Text,
    Button,
    Row
  } from 'better-svelte-email';

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

<Html>
  <Head />
  <Body class="bg-zinc-100">
    <Preview preview="Welcome to our platform!" />
    <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>
        <Text class="mt-3 text-zinc-600">
          Better Svelte Email converts Svelte components into email-safe HTML
          with full Tailwind support.
        </Text>
        <Row class="mt-6">
          <Button
            href="https://better-svelte-email.konixy.fr/docs"
            pX={24}
            pY={14}
            class="mr-2 rounded-lg bg-orange-600 text-white"
          >
            Explore the docs
          </Button>
          <Button
            href="https://github.com/Konixy/better-svelte-email"
            pX={24}
            pY={14}
            class="ml-2 rounded-lg border border-zinc-200 text-zinc-900"
          >
            View on GitHub
          </Button>
        </Row>
      </Section>
    </Container>
  </Body>
</Html>
The Preview component sets the text shown in inbox previews before the email is opened.
2

Render the Email to HTML

Use the Renderer class to convert your Svelte component into email-safe HTML.
import Renderer from 'better-svelte-email/render';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer();

const html = await renderer.render(WelcomeEmail, {
  props: { name: 'John' }
});

console.log(html);
The rendered HTML will have:
  • Tailwind classes converted to inline styles
  • Media queries injected into <head> for responsive design
  • Email-safe DOCTYPE and structure
The Renderer class processes Tailwind utilities and outputs production-ready HTML that works across all major email clients.
3

Send the Email

Integrate with your email service provider to send the rendered HTML. This example uses Resend, but you can use any provider.

Using SvelteKit API Route

import Renderer from 'better-svelte-email/render';
import { Resend } from 'resend';
import { env } from '$env/dynamic/private';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer();
const resend = new Resend(env.PRIVATE_RESEND_API_KEY);

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

  const html = await renderer.render(WelcomeEmail, {
    props: { name }
  });

  const { data, error } = await resend.emails.send({
    from: '[email protected]',
    to: email,
    subject: 'Welcome to our platform!',
    html
  });

  if (error) {
    return new Response(JSON.stringify({ error }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' }
    });
  }

  return new Response(JSON.stringify({ success: true, data }), {
    headers: { 'Content-Type': 'application/json' }
  });
}

Using Other Email Providers

Better Svelte Email works with any email provider. Just pass the rendered HTML to their API:
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Welcome!',
  html
});
4

Add Plain Text Version (Optional)

For better deliverability and accessibility, include a plain text version of your email.
import Renderer, { toPlainText } from 'better-svelte-email/render';
import { Resend } from 'resend';
import { env } from '$env/dynamic/private';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer();
const resend = new Resend(env.PRIVATE_RESEND_API_KEY);

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

  const html = await renderer.render(WelcomeEmail, {
    props: { name }
  });

  // Generate plain text version
  const plainText = toPlainText(html);

  await resend.emails.send({
    from: '[email protected]',
    to: email,
    subject: 'Welcome to our platform!',
    html,
    text: plainText  // Add plain text version
  });

  return new Response('Email sent');
}
The toPlainText function automatically strips images and preview text, leaving readable content.

Advanced Configuration

Custom Tailwind Configuration

Extend the default Tailwind theme with your brand colors and custom configuration:
import Renderer from 'better-svelte-email/render';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer({
  tailwindConfig: {
    theme: {
      extend: {
        colors: {
          brand: '#FF3E00',
          'brand-dark': '#E03000'
        },
        fontFamily: {
          sans: ['Inter', 'sans-serif']
        }
      }
    }
  }
});

const html = await renderer.render(WelcomeEmail, {
  props: { name: 'John' }
});
Now you can use text-brand and other custom classes in your email components.

Inject App Theme Styles

Share CSS variables and theme styles between your app and emails:
import Renderer from 'better-svelte-email/render';
import layoutStyles from '$lib/styles/app.css?raw';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer({
  customCSS: layoutStyles  // Inject your app's CSS
});

const html = await renderer.render(WelcomeEmail, {
  props: { name: 'John' }
});
This is especially useful for integrating with component libraries like shadcn-svelte.
Learn more about custom Tailwind configuration in the Custom Tailwind Config guide.

Test Your Email

Visual Preview in Development

Better Svelte Email provides a built-in preview component for development:
<script>
  import EmailPreview from 'better-svelte-email/preview/EmailPreview.svelte';
  import WelcomeEmail from '$lib/emails/welcome.svelte';
</script>

<EmailPreview component={WelcomeEmail} props={{ name: 'John' }} />
Navigate to /preview in your browser to see a live preview with:
  • Desktop and mobile views
  • Component tree inspector
  • HTML and plain text output
  • Send test email functionality

Email Preview Guide

Set up the complete email preview environment.

Send Test Emails

Send test emails to yourself before production:
import Renderer from 'better-svelte-email/render';
import { Resend } from 'resend';
import { env } from '$env/dynamic/private';
import WelcomeEmail from '$lib/emails/welcome.svelte';

const renderer = new Renderer();
const resend = new Resend(env.PRIVATE_RESEND_API_KEY);

export async function POST() {
  const html = await renderer.render(WelcomeEmail, {
    props: { name: 'Test User' }
  });

  await resend.emails.send({
    from: '[email protected]',
    to: '[email protected]',  // Your email for testing
    subject: '[TEST] Welcome Email',
    html
  });

  return new Response('Test email sent');
}

What’s Next?

You’ve successfully created, rendered, and sent your first email! Here’s what to explore next:

Component Library

Explore all available components and their props.

Rendering Guide

Deep dive into the Renderer API and options.

Tailwind Support

Learn about responsive design and custom classes.

Sending Emails

Best practices for sending emails in production.

Example Templates

Need inspiration? Check out these example templates:
  • Vercel Invite Email: Team invitation with profile images
  • Apple Receipt: Transaction receipt with product details
  • Demo Email: Feature showcase with icons and CTAs
All examples are available in the GitHub repository.
Have questions? Check out the GitHub discussions or open an issue.

Build docs developers (and LLMs) love