Skip to content
← All systems

Local-business lead engine · call & WhatsApp cockpit

In daily use

Lead Generator + Outreach Cockpit

The system I actually run my calling day on.

Two programs over one database. The generator finds local businesses in a city, grades how weak or absent their web presence is, and writes an Excel call sheet you can update in three seconds while the phone is still at your ear. The cockpit reads the same database, drafts Hinglish WhatsApp follow-ups with Gemini, and walks a capped daily send list — then tracks replies, callbacks and outcomes.

1,760
Leads generated
9
Cities covered
313
Cold calls logged
216
Businesses rung

The hard part

How do you decide which of 1,760 businesses is worth a phone call?


By fetching every one of their websites and grading it. Missing, parked, broken, painfully slow, or not mobile-friendly are each a different sales conversation — and a business with a good site is not a prospect at all. 1,566 of the 1,760 came back worth pitching. Chains are filtered out by name, because a Lakmé franchise cannot buy a website from me.

The Outreach Cockpit dashboard: 1,760 leads, 1,566 worth pitching, 216 rung, 109 crossed out, a two-week dials-per-day chart totalling 313 dials, and a callbacks-due panel.
313 dials across two weeks, split into WhatsApp permission, callback, not interested, and not picked. The four bands add up to the day's dials by construction, so the bar is the tally.

Design decisions

01

Built around the three seconds you have on a call

The call sheet is an Excel workbook, one tab per category, rows pre-sorted so the best leads sit at the top. You type an outcome into a cell between sentences. The next run reads your edits back before it writes, so refreshing the data never costs you your notes — and it refuses to write over a workbook you have open rather than risk a half-written sheet.

02

It never sends anything itself

The cockpit writes the Hinglish WhatsApp message and opens the deep link. You press send, and it records that afterwards. That is a deliberate line: an automated WhatsApp sender risks a real number for a message a human can send in ten seconds.

03

One do-not-call list, permanently

Someone who says no is crossed out across every city and every future run, in a file that survives database rebuilds. Nothing is deleted — the row stays, it is simply never offered again.

04

Callbacks are a cadence, not a memory

A promised callback becomes a dated row with outcome rules attached. The dashboard surfaces what is due and what is overdue, which is the whole difference between a pipeline and a list of names you once rang.

05

One writer per table

One module is the only writer of the leads table, another the only writer of send state, another the only writer of the config file. Timestamped backups are taken before anything is overwritten, twenty deep. For a system holding the only copy of two weeks of calling, that discipline is the feature.

Stack

  • Python
  • Playwright
  • FastAPI
  • SQLite
  • React 19
  • Vite
  • TypeScript
  • Tailwind v4
  • Gemini 2.5 Flash
  • Docker

My part in it

Sole engineer, and the only user — I built it for my own calling day.


What is not done

A local-first tool for one operator: SQLite, Excel, and three test scripts run directly rather than a full pytest suite. It is the least architecturally ambitious system here and the one that has produced the most revenue.