Send an email
What you'll build: a welcome email, written as a Vue component and sent from a server route. In development it
prints in the terminal, and outside development a real provider delivers it.
Prerequisites
- The workspace starter, or another host app.
- Notify, which Auth, Users, Forms and Subscriptions install for you.
- Email Templates.
The paths below are for the starter's apps/web.
1. Add Email Templates
Notify sends the email, and Email Templates turns a Vue component into its HTML. Install Email Templates in the app:
pnpm --filter ./apps/web add @frigear-nu/email-templates
modules yourself. Being a dependency of another module is not enough: the templates of those
modules do not render.export default defineNuxtConfig({
modules: ['@frigear-nu/notify', '@frigear-nu/email-templates'],
notify: { email: { driver: 'log' } },
})
2. Write the template
A template is a Vue component, so you write the email with the same tools as a page. Every top-level .vue file in
app/emails is a template, named by its file name:
<script setup lang="ts">
import { EmailButton, EmailDivider, EmailHeading, EmailLayout, EmailLinkFallback, EmailText } from '@frigear-nu/email-templates/components'
defineProps<{ name: string, url: string }>()
</script>
<template>
<EmailLayout :preview="`Welcome, ${name}!`">
<ESubject>Welcome, {{ name }}</ESubject>
<EmailHeading>Welcome, {{ name }}!</EmailHeading>
<EmailDivider />
<EmailText>Thanks for signing up. Click the button below to get started.</EmailText>
<EmailButton :href="url">Get started</EmailButton>
<EmailLinkFallback :href="url" />
</EmailLayout>
</template>
<ESubject>sets the subject.- Import the
Email*components. Only the renderer's ownE*components are global.
3. Send it
sendEmailTemplate is auto-imported in server code. The template name and its props are typed, so a misspelled name
or a missing prop does not compile:
export default defineEventHandler(async (event) => {
const { user } = await requireAuth(event, { sessionOnly: true })
await sendEmailTemplate('welcome', { name: user.name, url: 'https://example.com/account' }, {
to: user.email,
replyTo: 'support@frigear.nu',
})
return { sent: true }
})
The third argument is an EmailNotification without body, plus three optional fields:
| Field | Purpose |
|---|---|
subject | Overrides <ESubject>. Required when the template has none. |
text | Your own plain text, or false for HTML only. |
locale | The locale to render the template in. |
dispatchEmailNotification({ to, subject, body, text }) from Notify.POST /api/welcome answers { "sent": true }, and the terminal running
pnpm dev prints the email.4. Choose a driver
The log driver prints emails to the terminal. That is the safe default for development. Switch drivers per
environment with variables, which win over nuxt.config.ts:
| Variable | Purpose |
|---|---|
NUXT_NOTIFY_EMAIL_DRIVER | log (default), resend, ses or cloudflare. |
NUXT_NOTIFY_EMAIL_FROM | The sender address, for example Frigear <no-reply@frigear.nu>. |
NUXT_NOTIFY_EMAIL_RESEND_API_TOKEN | The API token, with the resend driver. |
ses and cloudflare have their own credentials. A missing one fails the send, with an error that names the
variable.
Next steps
- Sell event tickets – send this email from the
events:ticket:paidhook. - Email Templates – use the components and branding, override the module emails by file name, and preview them in DevTools.
- Notify – send SMS and simple notifications, or write your own driver.