Skip to main content

Overview

The createEmail() function returns a SvelteKit form action that renders email components to HTML. Use this with the EmailPreview component to preview your email templates in the browser.

Function Signature

function createEmail(options?: CreateEmailOptions): {
  'create-email': (event: RequestEvent) => Promise<CreateEmailResponse>
}

Parameters

options
CreateEmailOptions
default:"{}"
Optional configuration object
options.renderer
Renderer
Custom renderer instance with your Tailwind config. If not provided, uses default renderer

Return Type

actions
object
SvelteKit actions object to be exported from +page.server.ts
'create-email'
FormAction
Form action that handles email rendering requestsSuccess Response:
body
string
Formatted HTML of the rendered email
source
string | null
Source code of the Svelte component
Error Response:
status
number
HTTP status code (400 or 500)
error
object
Error details
message
string
Error description

Usage

Basic Example

+page.server.ts
import { createEmail } from 'better-svelte-email/preview';

export const actions = createEmail();

With Custom Renderer

Use a custom renderer to apply your own Tailwind configuration:
+page.server.ts
import { createEmail } from 'better-svelte-email/preview';
import Renderer from 'better-svelte-email/render';

const renderer = new Renderer({
  tailwindConfig: {
    theme: {
      extend: {
        colors: {
          brand: '#FF3E00',
          accent: '#40B3FF'
        },
        fontFamily: {
          sans: ['Inter', 'system-ui', 'sans-serif']
        }
      }
    }
  }
});

export const actions = createEmail({ renderer });

Complete Setup with EmailPreview

+page.server.ts
import { emailList, createEmail, sendEmail } from 'better-svelte-email/preview';
import { PRIVATE_RESEND_API_KEY } from '$env/static/private';
import Renderer from 'better-svelte-email/render';

const renderer = new Renderer({
  tailwindConfig: {
    theme: {
      extend: {
        colors: {
          brand: '#FF3E00'
        }
      }
    }
  }
});

export function load() {
  const emails = emailList();
  return { emails };
}

export const actions = {
  ...createEmail({ renderer }),
  ...sendEmail({ resendApiKey: PRIVATE_RESEND_API_KEY, renderer })
};
+page.svelte
<script>
  import { EmailPreview } from 'better-svelte-email/preview';
  
  export let data;
</script>

<EmailPreview {data} />
The EmailPreview component automatically calls the create-email action when you select an email template from the list.

How It Works

  1. The EmailPreview component submits a form with file and path parameters
  2. The create-email action receives the form data
  3. The email component is dynamically imported from your project
  4. The component is rendered to HTML using the provided renderer
  5. The HTML is formatted with Prettier for readability
  6. Both the rendered HTML and source code are returned to the client

Error Handling

Missing Parameters (400)

If file or path parameters are missing from the form data:
{
  "status": 400,
  "body": {
    "error": "Missing file or path parameter"
  }
}

Render Error (500)

If the email component fails to import or render:
{
  "status": 500,
  "error": {
    "message": "Failed to import email component 'welcome.svelte'. Make sure the file exists and includes the <Head /> component."
  }
}
All email components must include the <Head /> component from better-svelte-email to render properly. Missing this component will cause render errors.

Performance Considerations

  • Email components are dynamically imported on each request
  • The renderer processes Tailwind CSS classes and inlines styles
  • Prettier formats the output HTML (adds ~50-100ms)
  • Consider caching rendered emails in production if performance is critical
  • emailList() - Get list of available email components
  • sendEmail() - Send rendered emails via Resend
  • Renderer - Learn more about custom Tailwind configuration

Build docs developers (and LLMs) love