--- name: email-resend description: Email sending via Resend API for contact forms and booking requests with locale-aware templates. Use when implementing email notifications, contact form submissions, or transactional emails. --- # Email with Resend ## Environment Setup ```bash # .env.local RESEND_API_KEY=re_... CONTACT_TO_EMAIL=hello@studioname.com ``` ## Resend Client ```tsx // lib/resend.ts import { Resend } from 'resend'; export const resend = process.env.RESEND_API_KEY ? new Resend(process.env.RESEND_API_KEY) : null; export function hasResend(): boolean { return resend !== null; } ``` ## Contact Form Email ```tsx // lib/emails/contact.ts import { resend } from '@/lib/resend'; import type { Locale } from '@/i18n.config'; interface ContactEmailParams { name: string; email: string; phone?: string; message: string; locale: Locale; } export async function sendContactEmail({ name, email, phone, message, locale, }: ContactEmailParams) { if (!resend) { console.log('Resend not configured, skipping email'); return { success: false, error: 'Email not configured' }; } const toEmail = process.env.CONTACT_TO_EMAIL!; try { await resend.emails.send({ from: 'Studio Contact ', to: toEmail, replyTo: email, subject: `New Contact Form Submission from ${name}`, html: `

New Contact Form Submission

Name: ${name}

Email: ${email}

${phone ? `

Phone: ${phone}

` : ''}

Message:

${message.replace(/\n/g, '
')}


Submitted from: ${locale} locale

`, }); return { success: true }; } catch (error) { console.error('Failed to send email:', error); return { success: false, error: 'Failed to send email' }; } } ``` ## Booking Request Email ```tsx // lib/emails/booking.ts import { resend } from '@/lib/resend'; import type { Locale } from '@/i18n.config'; interface BookingEmailParams { name: string; email: string; phone?: string; goals: string; experienceLevel: string; injuries?: string; preferredTimes: string; sessionType: 'in-person' | 'online'; locale: Locale; } const subjectByLocale: Record = { 'pt-PT': 'Novo Pedido de Sessão', 'en': 'New Booking Request', 'tr': 'Yeni Rezervasyon Talebi', 'es': 'Nueva Solicitud de Reserva', 'fr': 'Nouvelle Demande de Réservation', 'de': 'Neue Buchungsanfrage', }; export async function sendBookingEmail(params: BookingEmailParams) { if (!resend) { console.log('Resend not configured, skipping email'); return { success: false, error: 'Email not configured' }; } const toEmail = process.env.CONTACT_TO_EMAIL!; try { // Email to studio await resend.emails.send({ from: 'Studio Booking ', to: toEmail, replyTo: params.email, subject: `${subjectByLocale[params.locale]}: ${params.name}`, html: generateBookingHtml(params), }); // Confirmation email to client await resend.emails.send({ from: 'Studio Name ', to: params.email, subject: getConfirmationSubject(params.locale), html: generateConfirmationHtml(params), }); return { success: true }; } catch (error) { console.error('Failed to send booking email:', error); return { success: false, error: 'Failed to send email' }; } } function generateBookingHtml(params: BookingEmailParams): string { return `

New Booking Request

${params.phone ? ` ` : ''} ${params.injuries ? ` ` : ''}
Name ${params.name}
Email ${params.email}
Phone ${params.phone}
Session Type ${params.sessionType}
Experience ${params.experienceLevel}
Goals ${params.goals}
Injuries/Notes ${params.injuries}
Preferred Times ${params.preferredTimes}

Locale: ${params.locale}

`; } function getConfirmationSubject(locale: Locale): string { const subjects: Record = { 'pt-PT': 'Recebemos o seu pedido de sessão', 'en': 'We received your booking request', 'tr': 'Rezervasyon talebinizi aldık', 'es': 'Recibimos tu solicitud de reserva', 'fr': 'Nous avons reçu votre demande', 'de': 'Wir haben Ihre Anfrage erhalten', }; return subjects[locale]; } function generateConfirmationHtml(params: BookingEmailParams): string { // Localized confirmation message return `

Thank you for your booking request!

Hi ${params.name},

We've received your request and will get back to you within 24 hours.

Best regards,
Studio Name

`; } ``` ## Server Action with Email ```tsx // lib/actions/contact.ts 'use server'; import { contactFormSchema } from '@/lib/validations'; import { sendContactEmail } from '@/lib/emails/contact'; import type { Locale } from '@/i18n.config'; export async function submitContactForm(formData: FormData, locale: Locale) { const rawData = { name: formData.get('name'), email: formData.get('email'), phone: formData.get('phone'), message: formData.get('message'), }; const result = contactFormSchema.safeParse(rawData); if (!result.success) { return { success: false, errors: result.error.flatten().fieldErrors, }; } const emailResult = await sendContactEmail({ ...result.data, locale, }); if (!emailResult.success) { return { success: false, errors: { _form: ['Failed to send message. Please try again.'] }, }; } return { success: true }; } ``` ## Fallback Without Resend ```tsx // When RESEND_API_KEY is not set export function ContactForm() { const hasEmail = hasResend(); if (!hasEmail) { return (

Contact us directly at:

hello@studioname.com
); } return ; } ```