03 / LeadPilot · live app
Lead capture and enrichment you can open and use. Next.js and Postgres, queued enrichment, real deploy with no mock data.
LeadPilot is a live app for capturing leads and enriching them without losing any along the way. You open it, fill the form, and the row lands in Postgres. Enrichment runs in the background, and the dashboard counts you see are real, not seeded fixtures.
The emphasis was shipping, not mocking. No demo data, no screenshot flow that never went live. The live card on the portfolio points at the same deploy you can try.
Limitation: enrichment is rate limited by the provider. Bulk imports queue and finish in order instead of all at once.
Next.js handles the routes, Postgres holds the truth, and a tiny queue makes enrichment resilient. The key idea is never drop a lead when the upstream says slow down.
// POST /api/leads · write and return the row
import { sql } from '@/lib/db'
export async function POST(req: Request) {
const { name, email, company } = await req.json()
const [row] = await sql`
insert into leads (name, email, company) values
(${name}, ${email}, ${company}) returning *
`
await queue.add('enrich', { leadId: row.id })
return Response.json(row)
}
// never drop a lead, queue it and retry
export async function enrichLead(lead) {
try {
await enrich(lead)
await sql`update leads set status='enriched' where id=${lead.id}`
} catch (err) {
if (isRateLimit(err)) {
await queue.add('enrich', lead, { delay: 60000 })
} else throw err
}
}
// counts come from the DB, not fixtures
export async function getCounts() {
const [{ count }] = await sql`
select count(*)::int as count from leads
where created_at > now() - interval '7 days'
`
return count
}
A live deploy is a stricter reviewer than a screenshot. If adding a lead does not stick, you find out right away. That feedback loop kept the scope small and the data honest.