Spacerr sends transactional email through Resend and renders email bodies with React Email templates. Auth, contact, onboarding, and support flows all go through the same mail helper.
What It Sends
The email layer includes:
- Welcome email after signup.
- Email verification.
- Magic sign in links.
- Password reset links.
- Contact form submissions to the support inbox.
- Support ticket notifications created by AI tools.
Sending Layer
The Resend client lives in src/features/emails/lib/emails.lib.ts.
export const getResend = () => {
const apiKey = ServerEnv.RESEND_API_KEY
if (!apiKey) return null
return new Resend(apiKey)
}
export async function sendMail(options: SendMailOptions): Promise<void> {
const resend = getResend()
if (!resend) {
throw new Error("Email not sent: RESEND_API_KEY is not set.")
}
const { error } = await resend.emails.send({
from: ServerEnv.RESEND_FROM_EMAIL,
to: options.to,
subject: options.subject,
react: options.react,
})
if (error) {
throw new Error(error.message)
}
}Keep provider specific delivery code here. Feature code should call the email actions, not Resend directly.
Email Actions
Email actions live in src/features/emails/lib/emails.actions.ts.
await sendMail({
to,
subject: `Welcome to ${SiteConfig.name}`,
react: WelcomeEmailTemplate({ firstName }),
})Email actions keep payload creation centralized. Validation belongs in the action or the caller that owns the flow, so malformed payloads do not reach the provider.
Templates
Templates live under src/features/emails/templates.
src/features/emails/templates
contact-submission.template.tsx
email-verification.template.tsx
magic-sign-in.template.tsx
reset-password.template.tsx
welcome.template.tsxUse these files for layout, subject specific copy, and React Email markup. Keep delivery logic in the email actions.
Auth Emails
Better Auth calls the email actions for verification, password reset, and magic links.
magicLink({
sendMagicLink: async ({ email, url }) => {
await sendMagicLinkEmail({ to: email, url })
},
})The auth setup page covers the provider values. This page is about where the email behavior lives in code.
Contact And Support
Contact form submissions are sent to SUPPORT_EMAIL. AI support ticket tools can also use the email layer when a user asks for support escalation.
await sendContactSubmissionEmail({
firstName,
lastName,
email,
subject,
message,
})Support ticket creation should stay limited and intentional. The assistant should answer from available context first, then create a ticket only when the user explicitly asks for escalation.
Production Email
For production, verify your sending domain in Resend before sending real email. Start with the Resend domain verification docs, then update RESEND_FROM_EMAIL to use that verified domain.
Where To Customize
Use these files first:
src/features/emails/lib/emails.lib.tsfor the Resend client and shared send helper.src/features/emails/lib/emails.actions.tsfor product email actions.src/features/emails/templatesfor React Email templates.src/features/auth/lib/auth.tsfor auth email hooks.src/features/contact/actions/submit-contact-form.action.tsfor contact form delivery.src/features/ai/chat/repositories/chat-tools.repository.tsfor support ticket workflows.