FindLeads — Generación de leads con CRM integrado
Un negocio sin sitio web es el mejor prospecto de un desarrollador web. FindLeads los busca en Google Places, marca los sin web como leads tier-1, y envuelve un mini CRM alrededor de los resultados.
Resumen
FindLeads es una herramienta personal de generación de leads: busca en la API oficial de Google Places (Text Search New) negocios por categoría y ubicación, marca negocios sin sitio web como prospectos tier-1 para outreach de diseño web, y añade un CRM ligero encima — notas por negocio, toggle de contactado, exportación CSV. Next.js 16 App Router con React 19, Neon Postgres vía Drizzle ORM, validación Zod en cada límite, y un diseño de job async deliberadamente sin cola: una fila de job en la base de datos, trabajo en background vía Next.js after(), y polling del lado cliente.
El problema
Prospectar para trabajo freelance web significa horas de scroll manual en mapas para responder una pregunta: ¿qué negocios reales y operativos cerca mío no tienen sitio web? Los datos existen en Google Places, pero los resultados crudos de API son inutilizables para seguimiento — sin memoria de quién ya contactaste, sin notas, sin export. La restricción de ingeniería interesante fue disciplina de scope: un usuario, sin auth, sin infraestructura de cola — ¿cuánta durabilidad puede entregar una fila de base de datos y diseño cuidadoso de concurrencia?
Preguntas abordadas
- 01
¿Puede un job en background reanudable sobrevivir crashes y workers duplicados usando solo Postgres y updates atómicos?
- 02
¿Cómo debe coexistir estado CRM durable con snapshots de búsqueda re-ejecutables para que un re-scrape nunca borre tus notas?
- 03
¿Hasta dónde llega una disciplina test-first en un MVP de una semana y una persona?
Metodología
Búsqueda Places y marcado tier-1
Los jobs de búsqueda llaman Google Places Text Search (New) por categoría + ubicación en texto libre. Cada respuesta se valida con Zod antes de tocar la base de datos, y negocios sin campo website se convierten en leads tier-1. Los resultados se almacenan como snapshots por job para que cada corrida de búsqueda sea reproducible.
Worker de jobs reanudable sin cola
En lugar de Redis o un servicio de cola, los jobs son filas de base de datos procesadas vía Next.js after() con polling cliente sobre SWR. El worker hace checkpoint de progreso y reclama trabajo mediante claims atómicos single-UPDATE, así un worker crasheado o duplicado nunca procesa dos veces — comportamiento fijado por tests de integración contra una base de datos de test Neon real.
Capa CRM y split durable/snapshot
El estado CRM durable (notas, status contactado) vive en una tabla businesses keyed por place_id, deliberadamente separado de snapshots de leads por job — re-scrapear una ciudad nunca resetea lo que sabes de un negocio. Exportación CSV cierra el loop para outreach real. 123 tests (unit + integración con DB real) cubren el pipeline; el código de test supera al de producto aproximadamente 1.35:1.
Resultados clave
Hallazgos clave
Postgres es una cola de jobs perfectamente válida a escala de un solo usuario: un claim atómico single-UPDATE te da crash-safety y duplicate-worker safety con cero infraestructura nueva.
Separar identidad durable (keyed por place_id) de snapshots de corrida es lo que hace un scraper re-ejecutable — el estado que te importa nunca debe vivir en estado que regeneras.
En builds asistidos por IA, la suite de tests es el contrato: 123 tests escritos junto a la implementación es lo que hizo "feature-complete" una afirmación verificable en lugar de una sensación.
Conclusión
FindLeads es un MVP completo y funcional construido en aproximadamente una semana — y honestamente scoped: single-user por diseño, localhost-only hasta ahora, con su propia auditoría de brechas de 15 ítems ordenados por severidad commiteada al repo. Es el ejemplo pequeño más claro del workflow detrás de los proyectos más grandes: planificar en fases, validar en límites, testear contra infraestructura real, y escribir lo que aún es débil.
Galería
