Skip to content

$email

The $email tool provides a type-safe way to send emails and render Vue-based email templates in your Nuxt application. This tool is designed for Hex Labs organizational use and requires a valid HEXLABS_KEY environment variable.

Features

  • Type-safe email sending with ArkType validation
  • Vue component email templates using @vue-email/render
  • Template-based emails with props support
  • Plain text and HTML email generation
  • Built-in error handling with Task pattern

Setup

First, define your email client with template components:

ts
// app/appkit/$email.ts
import { defineEmail } from '#appkit/tools'
import InvoiceEmail from '~/components/emails/Invoice.vue'
import WelcomeEmail from '~/components/emails/Welcome.vue'

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

Environment Setup

Ensure you have the required environment variable:

bash
HEXLABS_KEY="your-hexlabs-api-key"

API Reference

$email.send(email)

Send a plain email with text or HTML content.

Parameters:

  • email - Email object with the following properties:
    • from: string - Sender email (must be valid email)
    • to: string | string[] - Recipient email(s) (must be valid email(s))
    • subject: string - Email subject line
    • message?: string - Plain text message (optional)
    • html?: string - HTML content (optional)

Returns: Task<string> - Success message or error

ts
const result = await $email.send({
  from: 'noreply@example.com',
  to: 'user@example.com',
  subject: 'Welcome to our service',
  message: 'Thank you for signing up!',
  html: '<h1>Thank you for signing up!</h1>'
})

if (result.success) {
  console.log(result.data) // "Email sent"
} else {
  console.error(result.error)
}

$email.sendTemplate(name, props, email)

Send an email using a Vue component template.

Parameters:

  • name: keyof Options - Template name (must match key in defineEmail options)
  • props - Props object for the Vue component (type-safe based on component)
  • email - Email metadata object:
    • to: string | string[] - Recipient email(s)
    • from: string - Sender email
    • subject: string - Email subject line

Returns: Task&lt;string&gt; - Rendered HTML or error

ts
const result = await $email.sendTemplate('invoice', {
  customerName: 'John Doe',
  invoiceNumber: 'INV-001',
  amount: 99.99,
  items: [
    { name: 'Product A', price: 49.99 },
    { name: 'Product B', price: 49.99 }
  ]
}, {
  to: 'customer@example.com',
  from: 'billing@example.com',
  subject: 'Invoice INV-001'
})

if (result.success) {
  console.log('Template email sent successfully')
} else {
  console.error('Failed to send template email:', result.error)
}

Vue Email Templates

Create Vue components for your email templates using @vue-email/components:

vue
<!-- components/emails/Invoice.vue -->
<template>
  <Html>
    <Head>
      <title>Invoice {{ invoiceNumber }}</title>
    </Head>
    <Preview>Invoice {{ invoiceNumber }} for {{ customerName }}</Preview>
    <Body style="font-family: Arial, sans-serif;">
      <Container style="max-width: 600px; margin: 0 auto;">
        <Heading as="h1">Invoice {{ invoiceNumber }}</Heading>
        <Text>Dear {{ customerName }},</Text>
        <Text>Please find your invoice details below:</Text>
        
        <Section>
          <Row v-for="item in items" :key="item.name">
            <Column>{{ item.name }}</Column>
            <Column align="right">${{ item.price }}</Column>
          </Row>
          <Hr />
          <Row>
            <Column><strong>Total</strong></Column>
            <Column align="right"><strong>${{ amount }}</strong></Column>
          </Row>
        </Section>
        
        <Text>Thank you for your business!</Text>
      </Container>
    </Body>
  </Html>
</template>

<script setup lang="ts">
interface Props {
  customerName: string
  invoiceNumber: string
  amount: number
  items: Array<{ name: string; price: number }>
}

defineProps<Props>()
</script>

Template Rendering

The sendTemplate method automatically generates both HTML and plain text versions:

  • HTML version: Full styled email with Vue component rendering
  • Plain text version: Automatically extracted text content for email clients that don't support HTML

Error Handling

Both methods return a Task result that you should handle appropriately:

ts
const emailResult = await $email.send(emailData)

if (!emailResult.success) {
  // Handle validation errors
  if (emailResult.code === 400) {
    console.error('Invalid email data:', emailResult.error)
  }
  // Handle other errors
  else {
    console.error('Email sending failed:', emailResult.error)
  }
}

Validation

Email data is automatically validated using ArkType:

  • from and to fields must be valid email addresses
  • to can be a single email string or array of email strings
  • subject is required and must be a non-empty string
  • message and html are optional strings

Invalid data will return a validation error before attempting to send.

Integration

The email service integrates with the Hex Labs backend via the /api/hexlabs endpoint with service parameters:

  • service: "email"
  • target: "send"

This allows for centralized email handling and delivery through the Hex Labs infrastructure.

Best Practices

  1. Environment Variables: Always set HEXLABS_KEY in production
  2. Template Organization: Keep email templates in a dedicated components/emails/ directory
  3. Error Handling: Always check the Task result before assuming success
  4. Type Safety: Leverage TypeScript for template props and email data
  5. Preview: Use email preview tools to test templates before sending