|
Download docs/guide.md from abc1181/Leads: direct link, hf CLI and curl.
- Browser
- Download file 9.05 kB
-
https://huggingface.co/spaces/abc1181/Leads/resolve/main/docs/guide.md
- Command line
-
hf download hf://spaces/abc1181/Leads/docs/guide.md
-
curl -L -o guide.md https://huggingface.co/spaces/abc1181/Leads/resolve/main/docs/guide.md
9.05 kB
| # LeadGen β Step-by-Step Guide (Personal Tool by AJ) | |
| > Single-owner India SMB finder: Maps β no-website hunt β scoring β AI icebreakers β Sheets. No bulk sending from this server. | |
| --- | |
| ## 1) What you need before you start | |
| - A Gmail account (owner β this will be the *only* login allowed via `APP_ALLOW_EMAIL`) | |
| - A Hugging Face account (for the Space at `https://abc1181-leads.hf.space`) | |
| - Optional but recommended: a Google Cloud project (for Places + OAuth) β free tier is enough | |
| --- | |
| ## 2) Create the Hugging Face Space | |
| The code is already pushed to `abc1181/Leads` (Docker). Just configure envs: | |
| 1. HF β Space `abc1181/Leads` β **Settings β Variables** (non-secrets) and **Secrets** (tokens) | |
| 2. Set the essentials below (Section 3). The Space auto-restarts on save. | |
| 3. Check `https://abc1181-leads.hf.space/api/health` β should be `{"ok":true,"db":"ok","persistence":"on"}`. If `persistence:off`, the Space has no `/data` bucket β it will still run on ephemeral `/tmp` (banner shows), but add a bucket at `/data` in Space Settings for durability. | |
| --- | |
| ## 3) Env vars β what to create | |
| ### 3.1 Essentials (app won't work without these) | |
| Set in HF **Variables** unless marked **Secret**: | |
| | Key | Where | Value / How | | |
| |---|---|---| | |
| | `APP_ALLOW_EMAIL` | Variables | Your Gmail exactly β only this can sign in (`middleware.ts:39`, `lib/auth.ts:14`) | | |
| | `GOOGLE_CLIENT_ID` | Variables | From Google Cloud OAuth (see 4.1) | | |
| | `GOOGLE_CLIENT_SECRET` | **Secrets** | Same OAuth client | | |
| | `NEXTAUTH_SECRET` | **Secrets** | Random 32b hex: `openssl rand -hex 32` (already set) | | |
| | `NEXTAUTH_URL` | Variables | `https://abc1181-leads.hf.space` (already set) | | |
| | `PLACES_API_KEY` | **Secrets** | Google Places API key (see 4.2) β *or leave empty and use the free OSM/Ola rail (Section 4.3)* | | |
| Also needed (already set, don't change): `DATABASE_URL=file:/data/leads.db`, `CRON_SECRET`, `ENCRYPTION_KEY` | |
| ### 3.2 Optional β add when you want more coverage | |
| | Key | Where | Free tier | Notes | | |
| |---|---|---|---| | |
| | `OLA_API_KEY` | Secrets | 100k/API/mo free | India best free β `docs/maps-providers.md#5` | | |
| | `MAPPLS_CLIENT_ID` + `MAPPLS_CLIENT_SECRET` | Secrets | Free eval, no card | India best address hit β `docs/maps-providers.md#4` | | |
| | `FOURSQUARE_API_KEY` | Secrets | 500 free calls | Global fallback | | |
| | `HERE_API_KEY` | Secrets | ~5k-250k free (needs card) | Global fallback | | |
| | `ENRICH_PROVIDER=hunter` + `ENRICH_API_KEY` | Secrets | 25-50/mo free | Else phone is spine, emails stay `unknown` | | |
| | `LLM_BASE_URL` + `LLM_API_KEY` + `LLM_MODEL=mistral-large-latest` | Secrets | Your gateway | Else fallback templates (`lib/ai/fallback.ts`) | | |
| | `SMTP_HOST/PORT/USER/PASS` **or** `RESEND_API_KEY` + `DIGEST_TO` | Secrets/Vars | 100/d free | Else digest is in-app only | | |
| | `MOCK_SOURCES=1` | Variables | β | Use for demo with 50 Delhi fixtures, no keys | | |
| > **No billing?** Leave `PLACES_API_KEY` empty β the 6-provider rail (`lib/sources/maps.ts`) runs on **OSM Overpass (free, no key)** + `OLA_API_KEY`/`MAPPLS_*` if you set them. Add Google later and it stacks β no rebuild. | |
| --- | |
| ## 4) How to get each credential | |
| ### 4.1 Google OAuth (for Sign-in + Sheets) | |
| 1. https://console.cloud.google.com β Create project β **APIs & Services β OAuth consent screen** β External β fill App name, Support email β Save | |
| 2. **Credentials β Create Credentials β OAuth client ID** β Web application β Authorized redirect URI β add: `https://abc1181-leads.hf.space/api/auth/callback/google` β Create β copy **Client ID** and **Client Secret** β paste to HF as above. | |
| ### 4.2 Google Places API (New) β $200 free, needs billing | |
| 1. Same Cloud project β **APIs & Services β Enable APIs** β search **Places API (New)** β Enable | |
| 2. **Credentials β Create Credentials β API key** β Restrict β API restrictions β **Places API (New)** only β Save β copy to `PLACES_API_KEY`. | |
| 3. Enable billing (Billing β Link account) to get the $200 credit β you won't be charged inside free. Our use β $5-10 (`lib/sources/places.ts:50` caps to 60 + Details only for no-website). Quota bar turns amber at 80% and degrades to `partial`. | |
| ### 4.3 Free India maps (no billing) β Mappls + Ola | |
| - **Mappls:** https://www.mapmyindia.com/api β Sign up β Dashboard β Create project β If you have a **Static/REST key** (your case), set `MAPPLS_API_KEY`; if you have OAuth pair, set `MAPPLS_CLIENT_ID` + `MAPPLS_CLIENT_SECRET` β either works. Free eval, no card. | |
| - **Ola Maps:** https://maps.olakrutrim.com β Sign up (Krutrim Cloud) β Credentials β API Key β `OLA_API_KEY`. 100k/API/mo free from 2026-09-01. `GET https://api.olamaps.io/places/v1/nearbysearch?location=lat,lng&radius=&keyword=` header `X-API-KEY`. | |
| ### 4.4 Other free maps (optional) | |
| - **Foursquare:** foursquare.com/developers β My Apps β Create App β API Key β `FOURSQUARE_API_KEY` (500 free). | |
| - **HERE:** developer.here.com β Project β API Key β `HERE_API_KEY` (needs card, pay-as-you-grow). | |
| - **OSM Overpass:** No key. Always on at `https://overpass-api.de/api/interpreter`. | |
| Full per-provider table: `docs/maps-providers.md`. | |
| ### 4.5 Enrich (emails, optional) | |
| - Hunter: hunter.io β API key (25 free) β `ENRICH_API_KEY` with `ENRICH_PROVIDER=hunter` | |
| - Apollo: app.apollo.io β API key (50 free) β `ENRICH_PROVIDER=apollo` | |
| ### 4.6 LLM (AI drafts, optional) | |
| Any OpenAI-compatible gateway. Set `LLM_BASE_URL` (e.g. `https://api.mistral.ai/v1`), `LLM_API_KEY`, `LLM_MODEL=mistral-large-latest`. **Llama banned** on any provider (`lib/ai/llm.ts:44` β AUP). Prompts are PII-free (`lib/ai/prompts.ts:8`). | |
| ### 4.7 Email digest (optional) | |
| - Gmail: App Password β `SMTP_HOST=smtp.gmail.com`, `SMTP_PORT=587`, `SMTP_USER`, `SMTP_PASS`, `DIGEST_TO=you@gmail.com` | |
| - Resend: resend.com β API key β `RESEND_API_KEY` (100/d free) | |
| --- | |
| ## 5) Run locally (optional) | |
| ```bash | |
| cp .env.example .env.local # fill with your keys; use absolute DATABASE_URL | |
| # MUST be absolute locally (Prisma CLI vs app resolve differently): | |
| # DATABASE_URL="file:/abs/path/to/leads-app/data/leads.db" | |
| npm install --registry https://registry.npmjs.org/ | |
| npx prisma migrate dev # creates data/leads.db | |
| npm run dev # http://localhost:7860 | |
| npm test # 59 unit (lib 80% lines) | |
| # integration (mock): INTEGRATION=1 MOCK_SOURCES=1 DATABASE_URL="file:$PWD/data/test.db" npx vitest run | |
| ``` | |
| --- | |
| ## 6) How to use the app (morning loop) | |
| 1. **Searches β New search** β pick template (Health/Beauty, Food, B2B/Factory, MidMarket/Upgrade, Generic) β city + radius (geocoded & cached, `lib/geo.ts:4`) β keywords β Cap 20/50/100/200 β Create. Star it for nightly. | |
| 2. **Run search** β progress header (per-provider ms/quota) β tabs Hot/Warm/Cold (`lib/score.ts:65` threshold) β table (filter by status/source/email/band/phone, sort score/rating) β drawer (AI draft violet, Copy/Regenerate, notes, blocklist). | |
| 3. **Verify all** (concurrency 5, skips fresh <7d unless forced) β **Push to Sheets** (master `LeadGen Master`, tab per search, 21 cols, idempotent on emailβphoneβcompany|location via `lib/sheets.ts:rowKey`) β **CSV fallback** per run. | |
| 4. **Hot queue (`/hot`)** is the morning inbox β `j/k` move, `q` qualify, `c` copy icebreaker, `?` help. | |
| 5. **Dashboard** shows Hot/Warm/Cold donut, per-source yield, category intel (`Where the buyers are`), quotas ($0), recent runs. Bell shows unread Hot + quota warnings. | |
| 6. **Settings** β Quotas, Keys presence (masked), Scoring weights + Re-score, Templates, Sheets connect/disconnect (OAuth sealed `lib/crypto.ts`), Blocklist (undo), Danger (purge caches). | |
| **Nightly:** GitHub Actions `30 20 * * * UTC` (02:00 IST) pings `/api/health` 5Γ then `POST /api/cron/nightly` with `CRON_SECRET` (`jobs/runner.ts:38` sequential, `roles` rolled if >25min). Digest top-10 Hot to `DIGEST_TO` (self only) + in-app bell. | |
| --- | |
| ## 7) Troubleshooting | |
| - `https://abc1181-leads.hf.space/api/health` β `ok:true, db:ok, persistence:on` means good. `persistence:off` = no bucket at `/data` β still runs on `/tmp` but data resets on restart (banner shows). | |
| - Sign-in 500 β `GOOGLE_*` or `APP_ALLOW_EMAIL` wrong, or redirect URI not set to `https://abc1181-leads.hf.space/api/auth/callback/google`. | |
| - Search returns 0 / `partial` β check quota bars in Settings; with no keys, OSM/Ola still work if those keys are set. | |
| - Chrome "Deceptive site" β fixed in `c029112` by making `/`, `/privacy`, `/terms` public (no auto-Google redirect). If still cached, request review at https://transparencyreport.google.com/safe-browsing/search?url=https://abc1181-leads.hf.space | |
| --- | |
| ## 8) Branding & cost | |
| - Branding: **Made by AJ Β· personal tool** (sidebar/footer/landing, `components/app-shell.tsx:39`). No Vercel triangle. | |
| - Cost: $0 target (`docs/runbook.md`). Quota bars prove it. 80% banners + auto-degrade, never spend. | |
| Questions? See `PRD.md`/`TRD.md` checkboxes (210 ticked, 52 intentionally unticked for live/V1.1/V2/parked). | |