Back to Blog
AI & Automation
October 15, 2026
7 min read

AI Lead Follow-Up on Next.js and a CRM

The unglamorous half of AI lead follow-up: validate the form, save the lead first, notify second, and make a silent failure queryable. The pattern we run in production.

Lead Follow-UpNext.jsCRMEngineering
Featured Image

How should you wire lead capture before adding an AI agent?

Save the lead first, notify second, and make silence queryable. The database row is the durable record, the visitor never waits on a downstream service, and a missing notification must be distinguishable from a missing lead. An AI follow-up agent only works if the lead arrives intact, exactly once.

I am Eliran, founder of Cuanto Labs, a software company in Fort Lauderdale, Florida. Most AI lead follow-up content is about the clever part, the agent that texts a prospect within a minute. This post covers the capture side on our own Next.js site, then where an agent and a CRM plug in. The capture pattern is what we run, simplified. The agent section is design guidance, and I label it as such.

StepWhat it doesFailure it prevents
ValidateRate limit, honeypot, field checksBots and junk rows
InsertParameterized write, answers 500 only if the write failedReporting a saved lead as unsaved
Notify after the responseRuns once the visitor has their replyA slow mail provider blocking the form
Bound each channelHard timeout per channelOne provider holding the function open
Stamp the rowRecords that a channel deliveredSilent failures looking like a quiet week

What should the route handler validate first?

Validate everything before the database is touched. Our route handler rate limits to 5 requests per minute per IP, rejects invalid JSON with a 400, checks every field's shape and length, and uses an allow-list for the source value. A hidden honeypot input gets a normal success reply and nothing else.

The in-memory rate limiter is the right size for a marketing site and the wrong size for anything under real abuse pressure. Know which one you are.

The honeypot is an off-screen input with no label and no autofill hint, so real visitors never fill it. The silent success is deliberate: an error would tell the bot which field tripped you.

Why insert the lead before notifying anyone?

Because the insert is the only step that may answer "failed to save". Keep notification code out of the same try block. If a mail call threw inside it, the handler would answer 500 for a lead that was in fact saved, the client would retry, and you would get duplicate rows and still no notification.

Reporting a saved lead as unsaved is worse than a missed notification, so the error handling ends the moment the row exists. Use parameterized queries only: values travel as parameters and are never concatenated into the SQL string.

How do you notify without making the visitor wait?

Use the after() function from next/server, which runs work after the response has flushed. The visitor gets their success reply at once while the notification runs behind it. Wrap the call in a helper that never throws, and pass after in as an argument so it can be tested.

Two traps apply. A floating promise is not a substitute: on serverless, work not registered with after() can die when the function freezes after the response. And after() can throw synchronously outside a request scope, so log and swallow that failure. The row exists, so the response is still a success.

How do you stop one slow channel from breaking the rest?

Give every channel its own hard timeout and race the send against it. Ours is 5 seconds, with an abort signal passed to the provider, so one slow provider cannot hold the other channels or the function open. Email is the only channel today, and others can be added without touching the route.

Two smaller rules have paid for themselves. Every channel degrades to logging when its configuration is missing, so a missing API key is a no-op and not a crash. And provider error strings are a privacy surface, since a raw mail API error can contain the recipient address. Redact before logging.

How do you make a silent failure visible?

Stamp the row. After the notifier runs, check whether any channel reported delivered, and if so set a notified_at timestamp on the lead. The check is stricter than "not failed": a channel in log-only mode reports logged, and counting that would mark every preview-environment lead as handled.

Now a small watchdog can ask the database a plain question: which leads are older than N minutes, 15 in ours, with no notified_at? Run it on a schedule and send yourself the result. Error monitoring tells you about failures after you suspect something. The stamp tells you about the ones you never suspected.

If the stamp update itself fails, swallow it. The email went out, and the worst case is a duplicate ping from the watchdog, which is noisier than silence and far better than the reverse.

We also send a server-side conversion event from after() in production when the row is created, because ad blockers and closed tabs lose browser events. It carries the lead id and source, never the name, email or message.

Where does the AI follow-up agent plug in?

Everything above is the trigger. Once a lead is a row with an id, the agent should subscribe to "lead created" from the database or a queue, not be called inline from the route. The route stays fast and the agent can be retried on its own.

This is how I would wire it and how we scope it for clients.

  • • A state machine, not a chat log. A lead moves through new, contacted, replied, qualified, handed to a person and closed. The agent reads and writes the state, and your existing CRM stays the system of record.
  • • Approved templates. A person approves the sequence templates once and the agent fills them in. Anything outside a template goes to a person.
  • • Stop conditions built first. Any reply pauses automated sends and alerts a human. An opt-out phrase ends sends on that channel and is recorded. Attempts are capped per lead, with quiet hours and a human takeover flag the CRM can set.
  • • Write back to the CRM. Every send and reply becomes an activity on the lead record. Otherwise a salesperson will contact someone the agent already contacted.

Texting rules on consent, quiet hours and opt-outs are real legal constraints. Have counsel review your sequences. This is engineering experience, not legal advice.

What do we claim, and not claim?

We do not quote a response-time improvement, because our own sample is small. The design guarantees three things: a saved lead is never reported as unsaved, the visitor never waits on a mail provider, and a missing notification shows up in a query.

We build follow-up systems for Florida businesses at a fixed price from $5K, typically in 2 to 6 weeks, with the code and accounts transferring to you. Scope depends on how many lead sources it watches, which channels it sends on and which CRM it connects to. See the AI lead follow-up automation page, or read how fast to follow up with a lead.

Written by Eliran Yihye, founder of Cuanto Labs, on October 15, 2026.

Eliran Yihye, founder of Cuanto Labs

Cuanto Labs

Related Articles

What we build

Cuanto Labs is a software team in Fort Lauderdale, Florida. We build custom web apps, AI agents and Shopify stores at a fixed price, with the timelines and prices published up front.

Working in South Florida? See how we run projects in Miami, Fort Lauderdale and Aventura, or across the rest of the region.

Ready to Build Something Great?

Let's discuss how Cuanto Labs can help your business grow with custom software, AI solutions, and more.

Get in Touch
Book a call