Documentation Index Fetch the complete documentation index at: https://nuntly.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Better Email is an open-source plugin that brings unified email management to Better Auth. Instead of configuring emails in 8+ places, you can centralize everything: one provider, one renderer, lifecycle hooks, and type-safe templates.
Why Better Email?
When implementing Better Auth with full email features, you typically need to configure email callbacks in multiple locations: email verification, password resets, magic links, two-factor codes, organization invitations, and more. Each callback requires its own configuration and email logic.
Better Email consolidates all these callbacks into a single, unified interface with:
One provider configuration for all email types
Swappable providers (Nuntly, …)
Swappable renderers (React Email, MJML, Mustache, plain HTML)
Type-safe templates with TypeScript validation
Lifecycle hooks for logging and error handling
Consistent tag management across all email types
Installation
npm install @nuntly/better-email
Quick start with Nuntly provider
import { betterAuth } from 'better-auth' ;
import { betterEmail } from '@nuntly/better-email' ;
import { NuntlyProvider } from '@nuntly/better-email/providers/nuntly' ;
import { ReactEmailRenderer } from '@nuntly/better-email/renderers/react-email' ;
import { render } from '@react-email/components' ;
import { createElement } from 'react' ;
const email = betterEmail ({
provider: new NuntlyProvider ({
apiKey: process . env . NUNTLY_API_KEY ! ,
from: 'auth@yourapp.com' ,
}),
templateRenderer: new ReactEmailRenderer ({
render ,
createElement ,
templates: {
'verification-email' : VerificationEmail ,
'reset-password' : ResetPasswordEmail ,
'magic-link' : MagicLinkEmail ,
'verification-otp' : OTPEmail ,
'organization-invitation' : InvitationEmail ,
'change-email-verification' : ChangeEmailEmail ,
'delete-account-verification' : DeleteAccountEmail ,
'two-factor-otp' : TwoFactorOTPEmail ,
},
subjects: {
'verification-email' : 'Verify your email' ,
'reset-password' : 'Reset your password' ,
'magic-link' : 'Your sign-in link' ,
'verification-otp' : 'Your verification code' ,
'organization-invitation' : ( ctx ) => `Join ${ ctx . organization . name } ` ,
'change-email-verification' : 'Confirm email change' ,
'delete-account-verification' : 'Confirm account deletion' ,
'two-factor-otp' : 'Your two-factor code' ,
},
}),
});
export const auth = betterAuth ({
emailVerification: {
sendOnSignUp: true ,
},
emailAndPassword: {
enabled: true ,
},
plugins: [
email ,
twoFactor ({ sendOTP: email . helpers . twoFactor }),
organization ({ sendInvitationEmail: email . helpers . invitation }),
magicLink ({ sendMagicLink: email . helpers . magicLink }),
emailOTP ({ sendVerificationOTP: email . helpers . otp }),
],
});
Available providers
Better Email supports multiple email providers out of the box:
Nuntly Production-ready email delivery with tracking and analytics
Resend Modern email API for developers
Postmark Transactional email service
Mailgun Email delivery and validation
SES Email service from Amazon Web Services
SMTP Standard SMTP protocol support
Console Development mode logging
Available renderers
Choose the template renderer that fits your stack:
React Email : Use React components for email templates
React MJML : Combine React with MJML for responsive emails
MJML : Responsive email markup language
Mustache : Logic-less template engine
Default HTML : Simple HTML string templates
Lifecycle hooks
Apply consistent logging and error handling across all email types:
const email = betterEmail ({
provider: new NuntlyProvider ({
/* ... */
}),
templateRenderer: new ReactEmailRenderer ({
/* ... */
}),
onBeforeSend : async ( ctx , msg ) => {
console . log ( `Preparing ${ ctx . type } email to ${ msg . to } ` );
},
onAfterSend : async ( ctx , msg ) => {
console . log ( `Sent ${ ctx . type } to ${ msg . to } ` );
},
onSendError : async ( ctx , msg , err ) => {
console . error ( `Failed to send ${ ctx . type } :` , err );
},
});
Tag management
Add default tags to every email for analytics and filtering:
const email = betterEmail ({
provider: new NuntlyProvider ({
/* ... */
}),
templateRenderer: new ReactEmailRenderer ({
/* ... */
}),
defaultTags: [
{ name: 'app' , value: 'yourapp' },
{ name: 'environment' , value: process . env . NODE_ENV },
],
});
Every email automatically gets a { name: 'type', value: ctx.type } tag for filtering by email type.
Custom renderers
Implement the EmailTemplateRenderer interface for custom template rendering:
import { EmailTemplateRenderer , BetterAuthEmailContext } from '@nuntly/better-email' ;
class CustomRenderer implements EmailTemplateRenderer {
async render ( context : BetterAuthEmailContext ) : Promise <{ subject : string ; html : string ; text ?: string }> {
// Your custom rendering logic
}
}
Learn more
GitHub repository View source code and contribute
Blog post Read the announcement
Getting your Nuntly API key
To use Better Email with the Nuntly provider, you need an API key:
Sign up for a Nuntly account
Complete the account setup
Create an API key with send permissions
Add your sending domain
Once configured, Better Email will handle all Better Auth email delivery through Nuntly with tracking, webhooks, and analytics built in.