From 7355a3613d18a42f3fb173d73c6930ea10a318b8 Mon Sep 17 00:00:00 2001 From: Alejandro Veras Date: Mon, 12 Oct 2026 12:13:20 -0400 Subject: [PATCH] Show an on-screen success message instead of emailing visitors Co-Authored-By: Claude Opus 5.5 --- src/app/contact/actions.ts | 76 ++----------------------- src/app/globals.css | 25 ++++++++ src/components/content/contact-form.tsx | 12 ++-- 3 files changed, 36 insertions(+), 77 deletions(-) diff --git a/src/app/contact/actions.ts b/src/app/contact/actions.ts index f88bc44..84e8f43 100644 --- a/src/app/contact/actions.ts +++ b/src/app/contact/actions.ts @@ -1,20 +1,15 @@ "use server"; import { headers } from "next/headers"; -import { after } from "next/server"; -export type ContactState = { status: "idle" | "sent" | "error"; message?: string; copySent?: boolean }; +export type ContactState = { status: "idle" | "sent" | "error"; message?: string }; // Where enquiries land. Override with CONTACT_TO in the environment if it ever changes. const TO = process.env.CONTACT_TO || "rey@aigrowth360.io"; -// Resend's shared sender works without a verified domain, but only delivers to the address that -// owns the Resend account. Set CONTACT_FROM to an address on a domain verified in Resend -// (e.g. "AI Growth Technologies ") to also send visitors a confirmation. +// Resend's shared sender only delivers to the address that owns the Resend account. To send to TO +// from any other account, set CONTACT_FROM to an address on a domain verified in Resend +// (e.g. "AI Growth Website "). const FROM = process.env.CONTACT_FROM || "AI Growth Website "; -const CAN_EMAIL_VISITORS = Boolean(process.env.CONTACT_FROM); -const SITE = process.env.VERCEL_PROJECT_PRODUCTION_URL - ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}` - : "https://www.aigrowthtechnologies.com"; const MIN_FILL_MS = 3000; const MAX_LINKS = 3; @@ -55,56 +50,6 @@ async function sendEmail(apiKey: string, payload: Record) { if (!res.ok) throw new Error(`Resend ${res.status}: ${await res.text()}`); } -function confirmationEmail(name: string, rows: [string, string][], message: string) { - const first = name.split(/\s+/)[0]; - const text = [ - `Hi ${first},`, - "", - "Thanks for reaching out to AI Growth Technologies. Your message is with our team, and a strategist will review what you shared and get back to you shortly.", - "", - "Here's a copy of what you sent:", - "", - ...rows.map(([k, v]) => `${k}: ${v}`), - "", - message, - "", - "— The AI Growth Technologies team", - SITE, - ].join("\n"); - - const html = ` -
-
-
- AI Growth Technologies -
-
-

Message received

-

Thanks, ${escape(first)}. We’ve got it.

-

- Your message is with our team. A strategist will review what you shared and get back to you shortly. -

-

What you sent

- - ${rows - .map( - ([k, v]) => - ``, - ) - .join("")} -
${k}${escape(v)}
-

${escape(message)}

-
-
- AI Growth Technologies · Dubai · Houston · Miami · New York
- ${SITE.replace(/^https?:\/\//, "")} -
-
-
`; - - return { subject: "We received your message — AI Growth Technologies", text, html }; -} - export async function sendContact(_prev: ContactState, formData: FormData): Promise { // 1. Honeypot: real visitors never see or fill this field. if (clean(formData.get("company_url"), 200)) return silentlyDrop("honeypot"); @@ -165,16 +110,5 @@ export async function sendContact(_prev: ContactState, formData: FormData): Prom return { status: "error", message: "We couldn’t send your message." }; } - // The visitor's copy goes out after the response, and never fails the submission. - if (CAN_EMAIL_VISITORS) { - after(async () => { - try { - await sendEmail(apiKey, { to: [email], reply_to: TO, ...confirmationEmail(name, rows, message) }); - } catch (err) { - console.error("Contact form: could not send the visitor confirmation", err); - } - }); - } - - return { status: "sent", copySent: CAN_EMAIL_VISITORS }; + return { status: "sent" }; } diff --git a/src/app/globals.css b/src/app/globals.css index d39f7ac..aaf7646 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2598,3 +2598,28 @@ a { font-size: clamp(22px, 2.2vw, 30px); font-weight: 300; } + +.sent-mark { + width: 48px; + height: 48px; + margin-bottom: 8px; + fill: none; + stroke-width: 1.2; +} + +.sent-mark circle { + stroke: var(--grafite); +} + +.sent-mark path { + stroke: var(--rosso); + stroke-dasharray: 32; + stroke-dashoffset: 32; + animation: draw-check 0.7s var(--ease) 0.15s forwards; +} + +@keyframes draw-check { + to { + stroke-dashoffset: 0; + } +} diff --git a/src/components/content/contact-form.tsx b/src/components/content/contact-form.tsx index 30d3211..443703f 100644 --- a/src/components/content/contact-form.tsx +++ b/src/components/content/contact-form.tsx @@ -33,12 +33,12 @@ export default function ContactForm() { if (state.status === "sent") { return (
- Received -

Thanks — your message is with the team.

-

- We’ll review what you shared and get back to you shortly. - {state.copySent && " A confirmation with a copy of your message is on its way to your inbox."} -

+ +

Your message was sent successfully.

+

Thank you for reaching out. Our team will review what you shared and get back to you shortly.

); }