PE Deal Sourcing & Qualification
Lead discovery through to qualified deal for a private-equity funnel — BANT scoring with a rationale attached, and a heuristic that answers when the model can't.
- Role
- Architect & sole engineer
The application
Screens, captured from the running app
Booted against its seeded database and walked route by route — these are the real pages, not mockups.





The problem
A deal team's funnel is wide at the top and the work of narrowing it is manual: pull an Apollo or ZoomInfo export, enrich it, decide who is worth contacting, run a sequence, and record what came back. Most of that is judgement applied at volume, which is exactly the shape of work that gets skipped when the list is long.
Qualification with a rationale
Leads are scored on BANT — budget, authority, need, timing — plus firm-specific criteria. The model returns a rationale per dimension and any red flags, not a bare number.
This is the design decision the rest of the system hangs on. A deal team will not act on a score of 74. They will act on "authority: reached the operations lead, not the sponsor" — because that sentence tells them what to do next. A number that cannot be argued with is a number that gets ignored.
There is a deterministic heuristic scorer behind the same interface, using firmographics and engagement signals. It is worse than the model and it always answers — so the pipeline has no dead state when the API is down, over budget, or unavailable for policy reasons.
The pipeline is a state machine
new → enriched → contacted → meeting_set → qualified → diligence → closed_won | closed_lost
Transitions are explicit and timestamped, which makes time-in-stage a property of the data rather than something reconstructed later from activity logs. The funnel chart on the dashboard is a direct read of stage counts — the current seed carries 60 leads spread across all eight stages, with an 11-lead qualified cohort and a 50% win rate.
Source attribution rides along: inbound, LinkedIn, ZoomInfo, Apollo, manual. Knowing that inbound produced 20 of 60 leads is only useful next to knowing how many of each source converted, so the analytics join stage to source rather than reporting them separately.
Outreach
Multi-touch sequences across LinkedIn, email, Meta and phone, with per-step delays and enrollment tracking. Drafting is model-assisted with the same mock fallback. CRM sync is Salesforce-shaped and logged rather than sent, because a demo that writes to a real CRM is a demo nobody can run twice.
Stack
FastAPI with async SQLAlchemy over SQLite in development and PostgreSQL in production; Next.js 14 with SWR and Recharts on the front; the full mock provider layer meaning the entire funnel — import, enrich, score, sequence, report — runs with zero API keys.