Skip to content

$email

The $email SDK provides a convenient way to send plain emails or Vue-based email templates. It's powered by @vue-email/render and arktype for strict type safety and validation.

Note: Ensure HEXLABS_KEY is defined in your environment to authorize email sending.

Usage

Send a Plain Email

This must be sent from an email verified on amazon ses account.

ts
await $email.send({
    from: "hello@hexlabs.dev",
    to: "client@example.com",
    subject: "Welcome!",
    message: "Thanks for joining!",
})

This can be used client side because of auto secret injection. The nuxt module inject a proxy server route into the app. The SDK the sends a request to the proxy, the proxy attaches an auth header and sends off the request.

Define Your Email Templates

ts
import InvoiceEmail from "~/emails/InvoiceEmail.vue"

const { $email } = defineEmail({
    invoice: InvoiceEmail,
})

Send a Template Email

Typescript knows the type here based on your prop definitions.

ts
await $email.sendTemplate(
    "invoice",
    {
        name: "John Doe",
        amount: 420.69,
    },
    {
        from: "billing@hexlabs.dev",
        to: "john@example.com",
        subject: "Your Invoice",
    }
)

API

The email service is built on top of Amazon SES.

defineEmail(options)

Registers your email templates.

  • options: Record<string, Vue Component> — Map of template names to Vue components.

Returns an object with a $email client.

$email.send(body)

Sends a raw email. Validates using arktype.

Parameters:

  • from: string — must be a valid email address
  • to: string or string[] — recipient(s)
  • subject: string
  • message (optional): string — plain text version
  • html (optional): string — HTML version

$email.sendTemplate(name, props, meta)

Sends a rendered Vue component as an email.

Parameters:

  • name: keyof your options — the template name

  • props: props object passed to the Vue email component

  • meta:

    • from: string
    • to: string
    • subject: string

Returns:

  • The rendered HTML string (useful for logging or previewing).

Validation

Every email is validated using ArkType:

ts
const assertEmail = type({
    from: "string.email",
    to: "string.email[] | string.email",
    subject: "string",
    "message?": "string",
    "html?": "string",
})

Invalid emails will throw before sending, giving a clean DX.

Notes

  • This module is used only in the browser (window.location.origin).
  • You can optionally generate plain-text fallbacks using @vue-email/render.
  • Automatically sends both plain text and HTML for best email client support.

Creating Email Templates

Email providers such don't allow us to render most things using plain html and css. So we need a wrapper to hide the messy details of what does and doesnt work. @vue-email is a great solution for templating emails with a simple interface. Also, it automatically picks up your prop definitions and yells at you when you miss a prop.

Find out more here: VueEmail

vue
<!-- ~/emails/InvoiceEmail.vue -->
<template>
    <Html lang="en">
        <Text>Hi {{ name }},</Text>
        <Text>
            We're pleased to invite you to access your personal client portal. This platform is
            designed to make managing your projects, invoices, and communication as seamless as
            possible.
        </Text>
        <Text>
            You can log in using the link provided in your welcome email. If you have any questions
            or need assistance, please don't hesitate to reach out.
        </Text>

        <Link href="https://google.com/">Customer Portal</Link>
        <Text>We look forward to working with you!</Text>
    </Html>
</template>

<script setup lang="ts">
import { Html, Link, Text } from "@vue-email/components"

defineProps<{
    name: string
}>()
</script>

To send this template your will need to register it in your $email toolkit as described above. Email templates will be automatically rendered to normal html files and sent as a html string with inline css.

ts
import InvoiceEmail from "~/emails/InvoiceEmail.vue"

const { $email } = defineEmail({
    invoice: InvoiceEmail,
})

Once registered you can then use it in your app:

ts
await $email.sendTemplate(
    "invoice", // name of the template
    {
        // Template props
        name: "John Doe",
    },
    {
        // Email details
        from: "billing@hexlabs.dev",
        to: "john@example.com",
        subject: "Your Invoice",
    }
)