Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LeadHarvest

A self-hosted Google Maps business scraper with a full dashboard for managing cold calling leads. Built for web design agencies and sales teams.

Features

  • Google Maps scraping — search by business type and location, captures name, phone, address, website, rating, and a screenshot of their site
  • Multi-tenant — personal workspaces and shared team workspaces; switch between them instantly
  • Lead pipeline — track leads through New → Called → Interested → Not Interested → Sold
  • Activity log — per-lead history of every status change and note, with timestamps and user attribution
  • Scrape history — full log of every scrape job run across your workspaces
  • Analytics dashboard — leads over time, pipeline breakdown, top categories, team activity
  • Multi-user auth — bcrypt-hashed passwords, session-based auth, superadmin panel for managing users and teams
  • CSV export — filter-aware export respecting your active workspace, status, and search filters
  • Docker-first — runs as a single container with persistent SQLite and screenshot storage

Stack

  • Backend — Node.js, Express, Playwright (Chromium), better-sqlite3
  • Frontend — Vanilla JS, no framework
  • Auth — express-session + bcryptjs
  • Storage — SQLite (leads), local filesystem (screenshots)

Quick Start

Requirements

Setup

# 1. Clone the repo
git clone https://github.com/PocketYogurt/leadharvest.git
cd leadharvest

# 2. Create your environment file
cp .env.example .env
# Edit .env with your credentials

# 3. Create the data directory
mkdir -p data/screenshots

# 4. Build and start
docker compose build
docker compose up -d

Then open http://localhost:3737

Environment Variables

Copy .env.example to .env and set:

Variable Description
LH_USERNAME Admin login username
LH_PASSWORD Admin login password
LH_SESSION_SECRET Long random string for session signing
PORT Port to run on (default 3737)

Generate a secure session secret:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Docker Commands

# Start
docker compose up -d

# Stop
docker compose down

# View logs
docker compose logs -f

# Rebuild after code changes
docker compose build --no-cache && docker compose up -d

Project Structure

leadharvest/
├── src/
│   ├── server.js      # Express API + auth + routes
│   ├── scraper.js     # Playwright Google Maps scraper
│   └── db.js          # SQLite database layer
├── public/
│   ├── index.html     # Main dashboard
│   ├── login.html     # Login page
│   ├── admin.html     # User & team management (superadmin only)
│   ├── history.html   # Scrape history
│   └── analytics.html # Analytics dashboard
├── data/              # Created at runtime — not in git
│   ├── businesses.db  # SQLite database
│   └── screenshots/   # Website screenshots
├── .env.example       # Environment variable template
├── Dockerfile
└── docker-compose.yml

Reverse Proxy (Caddy)

leads.yourdomain.com {
    reverse_proxy localhost:3737
    header Cache-Control no-store
}

Notes

  • Scraping is done via headless Chromium inside the container
  • Google occasionally changes their Maps layout — check logs if scrapes return 0 results
  • Screenshots are stored in data/screenshots/ and served by Express
  • The data/ directory is mounted as a Docker volume so it persists across rebuilds

About

LeadHarvest - Self-hosted Google Maps lead scraper with multi-tenant dashboard, pipeline tracking, and team workspaces. Built for cold-calling campaigns.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages