Platform

Notify

Send email, SMS and simple notifications from any module, with the delivery service chosen once by your app.

Modules send email, such as a sign-in link or a receipt, without choosing an email service. Notify is where your app picks how email, SMS and simple notifications are delivered, per environment. For emails designed with Vue components, add Email Templates on top.

The package is @frigear-nu/notify. In-app toasts are not part of it: use useToast() from Nuxt UI.

What you get

  • Composables and helpers.
    • Server functions that send an email, an SMS or a simple notification, auto-imported in Nitro.
    • A log driver that prints each notification instead of sending it. On by default.
    • Email drivers for Resend, Amazon SES and Cloudflare Email Service, or a driver file of your own. Opt-in.
  • Emails. None of its own. It sends what other modules build.
ServerClientMobile
Installed for you: nothing. You add: nothing, unless you configure drivers; then add it to modules. Auth (server mode), Users, Forms, Subscriptions and Email Templates install Notify. Optional:Email Templates, to render emails from Vue templates.

Quick setup

Install the module

pnpm add @frigear-nu/notify

Configure it in nuxt.config.ts

List Notify in modules only to configure it. This setup sends email through Resend and SMS through your own driver:

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@frigear-nu/notify'],
  notify: {
    email: { driver: 'resend' },
    sms: { driver: '~/server/utils/twilio-sms-driver' },
    simple: { driver: 'log' },
  },
})
Store the API tokens and keys as secrets of your hosting platform, never in nuxt.config.ts. Anyone who has them can send email as you.

Set the environment variables

Set NUXT_NOTIFY_EMAIL_FROM and the credentials of your email driver, listed under Environment variables.

What you should see: with the log driver, the server console prints [notify] Dispatching notification: and the notification. With a real driver, the email arrives.

Options

Options go under the notify key. Each notification type has its own driver, and only the configured driver is loaded.

OptionTypeDefaultPurpose
email.driver'log' | 'resend' | 'ses' | 'cloudflare' | string'log'A built-in name, or a path to a file whose default export is an EmailDriver.
sms.driver'log' | string'log''log', or a path to a file whose default export is an SMSDriver.
simple.driver'log' | string'log''log', or a path to a file whose default export is a SimpleDriver.
push.driverstringnoneReserved. Typed, but not implemented.

email.driver set to a built-in name only sets the default. NUXT_NOTIFY_EMAIL_DRIVER overrides it at runtime. A path to a file is fixed at build time.

Environment variables

The built-in email drivers are read from runtimeConfig.notify.email at runtime, so each environment can use another service without a rebuild. They use plain fetch, with no dependencies. SES requests are signed with AWS Signature Version 4 through Web Crypto.

VariableUsed byPurpose
NUXT_NOTIFY_EMAIL_DRIVERalllog (default), resend, ses or cloudflare. Any other value throws when sending.
NUXT_NOTIFY_EMAIL_FROMresend, ses, cloudflareThe sender, such as Frigear <no-reply@frigear.nu>.
NUXT_NOTIFY_EMAIL_RESEND_API_TOKENresendAPI token.
NUXT_NOTIFY_EMAIL_SES_REGIONsesAWS region, such as eu-west-1. Uses the SES v2 API.
NUXT_NOTIFY_EMAIL_SES_ACCESS_KEY_IDsesAccess key id.
NUXT_NOTIFY_EMAIL_SES_SECRET_ACCESS_KEYsesSecret access key.
NUXT_NOTIFY_EMAIL_SES_SESSION_TOKENsesOptional, for temporary credentials.
NUXT_NOTIFY_EMAIL_CLOUDFLARE_ACCOUNT_IDcloudflareCloudflare account id (Email Service).
NUXT_NOTIFY_EMAIL_CLOUDFLARE_API_TOKENcloudflareAPI token.

A missing credential fails the send, with an error that names the variable to set.

Server

The dispatch functions and the definers are auto-imported in server code wherever the module is installed.

FunctionSignature
dispatchEmailNotification(notification: EmailNotification) => Promise<void>
dispatchSMSNotification(notification: SMSNotification) => Promise<void>
dispatchSimpleNotification(notification: SimpleNotification) => Promise<void>
defineEmailNotification, defineSMSNotification, defineSimpleNotificationTyped helpers that return the notification unchanged.
defineEmailDriver, defineSMSDriver, defineSimpleDriverTyped helpers that return the driver unchanged.
await dispatchEmailNotification({
  to: user.email,
  subject: 'Welcome!',
  body: '<p>Thanks for signing up.</p>',
  text: 'Thanks for signing up.',
})

await dispatchSMSNotification({
  to: user.phone,
  body: 'Your verification code is 123456.',
})

await dispatchSimpleNotification({
  title: 'New signup',
  text: `${user.email} just signed up.`,
})

Templates

Notify renders no templates itself. dispatchEmailNotification calls the notify:email hook before the driver runs, where Email Templates renders notification.template. Without a renderer, subject and body are sent as built.

Types

The types are exported from @frigear-nu/notify/types. The package root re-exports the notification, driver and ModuleOptions types.

interface EmailNotification<M = NotificationMeta> {
  to: string | string[]
  subject: string
  /** HTML body. */
  body: string
  /** Optional plain-text body. */
  text?: string
  /** Address replies go to (the `Reply-To` header). */
  replyTo?: string
  /** Template to render instead of subject/body/text, when a renderer is installed. */
  template?: { name: string, props?: Record<string, unknown>, locale?: string }
  meta?: M
}

interface SMSNotification<M = NotificationMeta> {
  to: string | string[]
  body: string
  meta?: M
}

interface SimpleNotification<M = Record<string, unknown>> {
  title: string
  text: string
  /** Optional URL to open when the notification is clicked. */
  url?: string
  meta?: M
}

type NotificationMeta<AdditionalMeta = Record<string, unknown>> = { driver?: string } & AdditionalMeta

type EmailDriver = (notification: EmailNotification) => Promise<void> | void
type SMSDriver = (notification: SMSNotification) => Promise<void> | void
type SimpleDriver = (notification: SimpleNotification) => Promise<void> | void

Custom driver

A driver is a function that delivers one notification. Point the driver option at a file whose default export is that function:

server/utils/resend-email-driver.ts
import type { EmailDriver } from '@frigear-nu/notify/types'

const sendWithResend: EmailDriver = async (notification) => {
  // call your provider with notification.to / subject / body / text / replyTo
}

export default sendWithResend

Store types

@frigear-nu/notify/types also exports StoredNotification and NotificationStore, a contract with put, get, list and delete for keeping notifications. Nothing in the module uses a store yet, and dispatch records nothing.

Hooks

A renderer such as Email Templates listens to these hooks.

HookWhenPayload
notify:email (Nitro)An email is about to go to the driver.{ notification }, replaceable
notify:email:templates (Nuxt)A renderer collects the template folders that modules ship.EmailTemplateSource[]: push { dir }

Next steps

  • Email Templates – render your emails from Vue components with your branding.
  • Send an email – send your first email from a server route.
  • Deployment – set the driver's secrets on your hosting platform.
Copyright © 2026