Skip to main content

1. Installation

npx nuxi module add lettermint
Add the module to nuxt.config.ts:
nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-lettermint']
})

2. Configuration

Set your API key in .env:
.env
NUXT_LETTERMINT_API_KEY=your-api-key
Or configure directly in nuxt.config.ts:
nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-lettermint'],
  lettermint: {
    apiKey: 'your-api-key',
    autoEndpoint: true  // Creates /api/lettermint/send (default: true)
  }
})
Never commit API keys to version control. Use environment variables in production.

3. Send Your First Email

Client-Side (Composable)

Use the useLettermint composable in Vue components:
<script setup lang="ts">
const { send, sending, error } = useLettermint()

async function sendWelcomeEmail() {
  await send({
    from: 'John Doe <john@yourdomain.com>',
    to: 'recipient@example.com',
    subject: 'Hello from Lettermint',
    text: 'This is a test email sent using the Lettermint Nuxt module.'
  })
}
</script>

<template>
  <button @click="sendWelcomeEmail" :disabled="sending">
    {{ sending ? 'Sending...' : 'Send Email' }}
  </button>
  <p v-if="error">{{ error }}</p>
</template>

Server-Side (API Routes)

Send emails from Nitro server routes:
server/api/send-welcome.post.ts
import { sendEmail } from '#imports'

export default defineEventHandler(async () => {
  return await sendEmail({
    from: 'John Doe <john@yourdomain.com>',
    to: 'recipient@example.com',
    subject: 'Welcome to our platform',
    html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
    tags: ['welcome']
  })
})

Fluent API

Build emails with a chainable API:
const lettermint = useLettermint()

await lettermint.email
  .from('John Doe <john@yourdomain.com>')
  .to('recipient@example.com')
  .subject('Hello from Lettermint')
  .html('<h1>Hello!</h1>')
  .tag('welcome')
  .send()

4. Email Features

HTML and Text Content

await send({
  from: 'John Doe <john@yourdomain.com>',
  to: 'recipient@example.com',
  subject: 'Your account is ready!',
  html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
  text: 'Welcome! Thanks for signing up.'
})

Multiple Recipients

await send({
  from: 'John Doe <john@yourdomain.com>',
  to: ['user1@example.com', 'user2@example.com'],
  cc: 'manager@yourdomain.com',
  bcc: 'archive@yourdomain.com',
  subject: 'Monthly Newsletter',
  html: '<h1>This Month\'s Updates</h1>'
})

Reply-To and Custom Headers

await send({
  from: 'support@yourdomain.com',
  to: 'customer@example.com',
  replyTo: 'help@yourdomain.com',
  subject: 'Support Ticket #12345',
  headers: {
    'X-Priority': '1',
    'X-Ticket-ID': '12345'
  },
  html: '<p>Your support ticket has been updated.</p>'
})

Metadata

Attach data for tracking and webhook payloads:
await send({
  from: 'notifications@yourdomain.com',
  to: 'user@example.com',
  subject: 'Order Confirmation',
  metadata: {
    orderId: 'ORD-12345',
    customerId: 'CUST-678'
  },
  html: '<p>Your order has been confirmed.</p>'
})
Metadata is included in webhook payloads but not sent to recipients.

Tags

Categorize emails for filtering and analytics:
await send({
  from: 'alerts@yourdomain.com',
  to: 'admin@example.com',
  subject: 'System Alert',
  tags: ['system-alerts'],
  html: '<p>Critical system alert detected.</p>'
})
One tag per message. The object API uses tags array, the fluent API uses .tag() method. See Tags documentation for more details.

Attachments

<script setup lang="ts">
const { send } = useLettermint()

async function sendWithAttachment(file: File) {
  const reader = new FileReader()

  reader.onload = async () => {
    const base64 = reader.result?.toString().split(',')[1]

    await send({
      from: 'invoices@yourdomain.com',
      to: 'customer@example.com',
      subject: 'Your Invoice',
      html: '<p>Please find your invoice attached.</p>',
      attachments: [{
        filename: file.name,
        content: base64
      }]
    })
  }

  reader.readAsDataURL(file)
}
</script>

5. Custom Endpoint

By default, the module creates an endpoint at /api/lettermint/send. Disable it for custom implementations:
nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-lettermint'],
  lettermint: {
    autoEndpoint: false
  }
})
Create your own endpoint with validation:
server/api/contact.post.ts
import { sendEmail } from '#imports'

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // Add your validation logic
  if (!body.email || !body.message) {
    throw createError({ statusCode: 400, message: 'Missing required fields' })
  }

  return await sendEmail({
    from: 'contact@yourdomain.com',
    to: 'support@yourdomain.com',
    subject: `Contact form: ${body.subject}`,
    html: `<p>From: ${body.email}</p><p>${body.message}</p>`,
    tags: ['contact-form']
  })
})

Next Steps

GitHub Repository

Find the complete source code, report issues, or contribute on GitHub.