What We Built Behind the New Homepage (It's Not What You'd Expect)
When we rebuilt the Twenty1 Media homepage last week, the goal wasn't a prettier portfolio. It was a sales page. Specifically: a page that converts visitors into audit requests, and routes those requests into a CRM without any manual steps.
The front end follows the Hormozi Grand Slam structure: hero with a concrete dream outcome, pain agitation with specific bullets ("ChatGPT helps with a paragraph, not a process"), capability grid, a featured case study, productized offers with named deliverables, and a risk reversal guarantee. The audit form sits at the bottom with its own section, and also embeds as a compact variant inside the offer cards.
That's the visible layer. Here's what happens when someone submits.
The Request Handler
The audit form posts to /api/audit-request. The route does four things in this order:
- Parse and validate the body with a Zod schema
- Check a honeypot field and silently return 200 if it's filled
- Send a confirmation email to the visitor and a notification email to us, in parallel
- Forward the lead to a webhook
The honeypot is a hidden field named something unrelated. Bots fill it. Humans don't. If it's present, we return success so the bot thinks it worked and moves on.
The Emails
We use Resend. Two emails fire in a Promise.all: one to the visitor confirming we received their request, one to us with the name, email, and the "what's broken" field they filled out.
The notification email has replyTo set to the visitor's address. So when we open that notification and hit reply, we're already writing directly to the lead. No copy-pasting, no looking up the email from a dashboard.
Both emails fire together. Neither blocks the other.
The Webhook: Fire and Forget
The lead also gets forwarded to LEAD_CAPTURE_WEBHOOK_URL, an n8n webhook that writes a row to Airtable. This is the part that needs to be fire-and-forget. If n8n is temporarily down, or the webhook is misconfigured, we don't want that to return a 500 to the person who just submitted their contact info.
The pattern is simple:
const forwardLead = forwardToLeadCapture({ name, email, problem });
const [userResult, notifyResult] = await Promise.all([sendUser, sendNotify]);
forwardLead.catch((err) => {
console.error("[audit-request] Lead capture webhook failed:", err);
});
We start the webhook fetch, then await the emails. After the emails resolve, we attach a .catch handler to the webhook promise so failures log without throwing. The response goes out before the webhook settles. Webhook failures show up in logs, not in user errors.
The payload includes a lead_magnet: "ai-audit-v1" tag so we can filter in Airtable by which form the lead came from. As we add more entry points, each one gets its own tag.
Why This Matters
A contact form that sends an email is a solved problem. What we wanted was a contact form that routes leads into a real CRM automatically, tags them by source, and doesn't silently fail without logging.
The whole pipeline: form submit, input validation, bot filtering, confirmation email, internal notification with reply-to wired, and CRM write, took a few hours to build clean. It runs without any manual intervention. Leads show up in Airtable, Isaac gets an email he can reply to in one click, and the visitor gets a confirmation that something actually happened.
That's the kind of infrastructure we build for clients. Now it's running on our own site.