Skip to content

avinro/limaleads

Repository files navigation

LimaLeads

Automated B2B outreach pipeline: Apollo → Supabase → Gmail drafts → Gemini AI personalization.

How it works

  1. Apollo poller (every 4h) — fetches new leads matching your ICP filters
  2. Gemini generator — creates personalized cold email drafts for each lead
  3. Gmail draft creator — pushes the draft directly into your Gmail inbox
  4. Sent detector (every 1-2 min) — detects when you send a draft and marks the lead as contacted
  5. Reply detector (every 5 min) — detects inbound replies and notifies via Slack
  6. Follow-up scheduler (daily) — auto-creates follow-up drafts for non-replies

Local setup

Prerequisites

  • Node.js 24+
  • npm

1. Install dependencies

npm install

2. Configure environment

cp .env.example .env

Fill in all values in .env:

Variable Description
APOLLO_API_KEY Master API key from Apollo settings. A regular key returns 403 — it must be a master key.
SUPABASE_URL Your Supabase project URL (https://<ref>.supabase.co)
SUPABASE_SERVICE_ROLE_KEY Service role key from Supabase project settings
SUPABASE_ANON_KEY Anon key from Supabase project settings
GEMINI_API_KEY API key from Google AI Studio
GMAIL_CLIENT_ID Google OAuth 2.0 client ID
GMAIL_CLIENT_SECRET Google OAuth 2.0 client secret
GMAIL_REFRESH_TOKEN Generated by running npm run gmail:auth
SLACK_WEBHOOK_URL Incoming webhook URL from your Slack app
ADMIN_API_TOKEN Secret token for the admin override endpoint

3. Run the worker

npm run dev

4. Gmail OAuth (first-time setup)

npm run gmail:auth

Follow the browser prompt. Copy the printed refresh token into GMAIL_REFRESH_TOKEN in .env.

Available scripts

Script Description
npm run dev Run the worker with hot-reload via tsx
npm run build Compile TypeScript to dist/
npm run typecheck Type-check without emitting files
npm run lint Run ESLint on src/
npm run lint:fix Auto-fix ESLint issues
npm run format Format src/ with Prettier
npm run format:check Check formatting (used in CI)
npm run eval:emails Generate 20 sample Gemini emails (Atelierra voice, EN/DE based on lead country) and write a reviewer doc to docs/eval-results-*.md (AVI-17 quality gate)

Lead language detection

Leads have a nullable country column (ISO-2 code, e.g. DE, AT, CH, GB). Outreach language is derived in code via detectLanguageFromCountry:

  • DE, AT, CH → German
  • Anything else (or null) → English

The active Supabase template (Default B2B Outreach) is still placeholder-based and unchanged in this issue. The Atelierra voice and language switching live in the Gemini prompt (src/integrations/geminiClient.ts) and the eval fixture (src/scripts/evaluateEmails.ts). They will be wired into the live pipeline by AVI-18.

Project structure

src/
  jobs/           # Cron jobs and schedulers
  integrations/   # Apollo, Gmail, Gemini, Slack API clients
  db/             # Supabase client and query helpers
  lib/            # Shared utilities (retry, logging, etc.)
  index.ts        # Main worker entrypoint
supabase/
  migrations/     # Versioned SQL migrations
docs/             # Spike documents and runbooks
.github/
  workflows/      # GitHub Actions CI

Docs

About

Automated B2B outreach pipeline: polls Apollo leads, generates personalized emails via Gemini AI, creates Gmail drafts for one-click review, and tracks replies.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors