From d76ecbda7ab000442ff84004073ac90c344511ad Mon Sep 17 00:00:00 2001
From: Matt
Date: Wed, 25 Mar 2026 21:35:47 +0100
Subject: [PATCH] feat: wire up email sending for configurator submissions
- Created src/lib/email.ts with Nodemailer + Poste.io SMTP
- sendBriefToClient: formatted HTML brief email to the lead
- sendLeadNotification: admin notification with submission details
- Emails fire non-blocking (don't delay the brief response)
- Only sends if SMTP_HOST and SMTP_PASS are configured
Co-Authored-By: Claude Opus 4.6 (1M context)
---
src/app/(frontend)/api/configure/route.ts | 24 +++++++
src/lib/email.ts | 84 +++++++++++++++++++++++
2 files changed, 108 insertions(+)
create mode 100644 src/lib/email.ts
diff --git a/src/app/(frontend)/api/configure/route.ts b/src/app/(frontend)/api/configure/route.ts
index ba5e404..1b66c44 100644
--- a/src/app/(frontend)/api/configure/route.ts
+++ b/src/app/(frontend)/api/configure/route.ts
@@ -1,4 +1,5 @@
import { NextRequest, NextResponse } from 'next/server';
+import { sendBriefToClient, sendLeadNotification } from '@/lib/email';
// ─── Types ────────────────────────────────────────────────────────────────────
@@ -206,6 +207,29 @@ export async function POST(request: NextRequest) {
// Generate the brief
const brief = generateMockBrief(body);
+ // Send emails (non-blocking — don't fail the response if email fails)
+ if (process.env.SMTP_HOST && process.env.SMTP_PASS) {
+ Promise.allSettled([
+ sendBriefToClient({
+ to: body.email,
+ name: body.name,
+ company: body.company,
+ brief,
+ }),
+ sendLeadNotification({
+ to: body.email,
+ name: body.name,
+ company: body.company,
+ brief,
+ services: body.services,
+ email: body.email,
+ }),
+ ]).catch(() => {
+ // Silently log — don't break the user flow
+ console.error('Email sending failed');
+ });
+ }
+
return NextResponse.json({ success: true, brief });
} catch {
return NextResponse.json(
diff --git a/src/lib/email.ts b/src/lib/email.ts
new file mode 100644
index 0000000..611f648
--- /dev/null
+++ b/src/lib/email.ts
@@ -0,0 +1,84 @@
+import nodemailer from 'nodemailer'
+
+const transporter = nodemailer.createTransport({
+ host: process.env.SMTP_HOST,
+ port: Number(process.env.SMTP_PORT) || 587,
+ secure: false,
+ auth: {
+ user: process.env.SMTP_USER,
+ pass: process.env.SMTP_PASS,
+ },
+})
+
+interface SendBriefEmailOptions {
+ to: string
+ name: string
+ company: string
+ brief: string
+}
+
+export async function sendBriefToClient({ to, name, brief }: SendBriefEmailOptions) {
+ const firstName = name.split(' ')[0] || 'there'
+
+ // Convert markdown-style **bold** to HTML
+ const htmlBrief = brief
+ .replace(/\*\*(.*?)\*\*/g, '$1')
+ .replace(/---/g, '
')
+ .replace(/\n\n/g, '
')
+ .replace(/\n/g, '
')
+
+ await transporter.sendMail({
+ from: `"LetsBe." <${process.env.SMTP_FROM || 'hello@letsbe.biz'}>`,
+ to,
+ subject: 'Your Project Brief from LetsBe.',
+ html: `
+
+
+
LetsBe.
+
+
+
Hi ${firstName},
+
+ Thank you for configuring your project with us. Here's your personalized brief:
+
+
+
+
+ Or reply to this email — we'll get back to you within 24 hours.
+
+
+
+ LetsBe. Digital Studio · Côte d'Azur, France
+
+
+ `,
+ })
+}
+
+export async function sendLeadNotification({ to, name, company, brief }: SendBriefEmailOptions & { services: string[]; email: string }) {
+ const adminEmail = process.env.ADMIN_EMAIL || 'hello@letsbe.biz'
+
+ await transporter.sendMail({
+ from: `"LetsBe. Configurator" <${process.env.SMTP_FROM || 'hello@letsbe.biz'}>`,
+ to: adminEmail,
+ subject: `New Lead: ${name}${company ? ` — ${company}` : ''}`,
+ html: `
+
+
New Configurator Submission
+
+ | Name: | ${name} |
+ | Company: | ${company || '—'} |
+ | Email: | ${to} |
+
+
${brief}
+
+ `,
+ })
+}