Canvass

Prospecting tool that maps local businesses, scores them as leads and drafts cold emails grounded in each one's real gaps.

Role
Design, engineering
Year
2026
Stack
TypeScript · Node · React · SQLite · Gemini · Docker
Canvass outreach queue with a ranked lead list and a drafted cold email in Spanish

The problem

Cold outreach breaks one of two ways: mass-send a generic template and everyone ignores it, or hand-write every email and send four a day. I built the middle path to run my own client acquisition: pull real business data off Google Maps, rank leads by fit, read each one's web presence, and draft an email that names a concrete gap. I use it most weeks, so it has to earn its place.

Key decisions

1Draw an area, get a queue

Draw a polygon over a map or type a neighborhood, pick a keyword and a grid resolution, and the tool tiles the area into cells and pulls matching businesses through a self-hosted scraper. Progress streams live over Server-Sent Events, and jobs are crash-safe: kill the server mid-scrape and it resumes from the last finished cell instead of starting over.

Canvass scraper with a polygon drawn over a Buenos Aires map, split into grid cells

2Deterministic lead scoring

Every lead gets a 0-to-1 score from pure math, so the queue is stable and I can explain any ranking. Ratings are pulled toward the database mean with Bayesian shrinkage, because a 5.0 with two reviews shouldn't outrank a 4.6 with four hundred, and that alone killed roughly 720 low-sample five-stars that flooded the top. Review volume, category budget, reachability and visible site pain fill out the weights.

3Read the website before pitching

A cheap crawl checks the basics: SSL, mobile viewport, booking, WhatsApp, PageSpeed. Then a gated vision pass renders the site in headless Chromium, screenshots desktop and mobile, and has Gemini read the design and name specific gaps. The expensive layer only runs for leads heading into outreach, which is the difference between an AI bill of a few cents and a few dollars. The draft cites one concrete problem, never a generic pitch.

Canvass analytics: pipeline funnel, lead density map of Buenos Aires and send-streak calendar

4Reply detection that distrusts machines

Every ten minutes an IMAP scan checks the inbox for contacted leads. The trap is that autoresponders look exactly like replies, so each match is classified with three signals: RFC 3834 auto-reply headers, out-of-office heuristics in English and Spanish, and velocity, because an answer inside three minutes of a cold send is a machine. Real replies leave the follow-up queue immediately; out-of-offices don't count as engagement.

Outcome

Runs in Docker on my machine and drives my actual acquisition: five thousand plus leads scraped, hundreds contacted, every billed AI call in a cost ledger that reports cost-per-send and cost-per-reply. Text stages run on free-tier models with a paid fallback that takes over automatically when one starts failing.