Skip to content

akwsa/stealth-ai

Repository files navigation

AI Lead Discovery System

Node Express Status License

A solo-builder dashboard that scans Reddit and Hacker News for high-intent prospects, scores them, and drafts AI-generated replies — wired end-to-end through a Lemon Squeezy payment pipeline.

This is not a spam tool. Every reply is reviewed by a human before posting. The system exists to compress the discovery → qualification → outreach → checkout loop for a one-person digital product business.


What it does

  1. Discover — Scans Reddit (RSS) and Hacker News (Algolia API) on a schedule for posts mentioning configurable keywords (e.g. "need scraper", "looking for python automation", "willing to pay for").
  2. Qualify — Auto-scores every lead 0-100 based on recency, content depth, keyword density, high-intent phrases, and (for HN) post traction.
  3. Draft — Leads scoring 50+ trigger an AI reply draft via Gemini or OpenAI. Output is a natural, helpful comment — not a sales pitch.
  4. Convert — Reviewed replies link to a landing page hosted from the same dashboard. Checkout runs through Lemon Squeezy.
  5. Account — Lemon Squeezy webhooks (HMAC SHA-256 verified) update local analytics the moment an order_created event lands. Daily CSV snapshots are written for backup and audit trail.

Architecture

   ┌────────────────┐     ┌────────────────┐
   │  Reddit RSS    │     │  HN Algolia    │
   └────────┬───────┘     └────────┬───────┘
            │                      │
            └──────────┬───────────┘
                       │
            ┌──────────▼──────────┐
            │  Scraper scheduler  │
            │  (interval-driven)  │
            └──────────┬──────────┘
                       │
            ┌──────────▼──────────┐
            │  Lead pool (JSON)   │
            │  + dedupe + scoring │
            └──────────┬──────────┘
                       │
        score >= 50 ───┼─── score < 50
                       │           │
            ┌──────────▼─────┐    skip auto-draft
            │  AI Draft Gen  │
            │ (Gemini/OpenAI)│
            └──────────┬─────┘
                       │
            ┌──────────▼──────────┐
            │  Dashboard (port    │
            │  3000) — review,    │
            │  edit, mark sent    │
            └──────────┬──────────┘
                       │
                 prospect clicks
                       │
            ┌──────────▼──────────┐
            │  Landing page       │
            │  /offer/:slug       │
            └──────────┬──────────┘
                       │
            ┌──────────▼──────────┐
            │  Lemon Squeezy      │
            │  checkout           │
            └──────────┬──────────┘
                       │  order_created
            ┌──────────▼──────────┐
            │  Webhook handler    │
            │  (HMAC SHA-256)     │
            └──────────┬──────────┘
                       │
            ┌──────────▼──────────┐
            │  Analytics + CSV    │
            │  snapshot           │
            └─────────────────────┘

Why I built it

I sell a few small digital products as a solo indie. The bottleneck is never "build the product" — it's qualified discovery. Manual Reddit + HN watching takes 60-90 minutes a day and most of it is filtering noise.

This system takes that 60-90 minutes down to ~10 minutes of human review per scan, with measurably better signal. The first 4 weeks of running it produced higher reply rates than my manual outreach because the AI draft removes the "blank page" friction that used to make me skip lukewarm leads.


Key features

Feature Detail
Multi-source scraping Reddit RSS + HN Algolia, configurable subreddits & keywords
0-100 scoring Recency + length + keyword density + high-intent phrase + HN traction
Auto-draft Threshold-gated AI reply generation (Gemini / OpenAI)
Dashboard UI Live log stream, lead review, draft editor, status workflow
REST API Full CRUD on leads, offers, settings, content, analytics
Landing pages Server-rendered offer pages at /offer/:slug
Webhook receiver Lemon Squeezy order_created with HMAC SHA-256 signature verification
CSV export RFC 4180 compliant; manual download or daily snapshot to data/exports/
Logs API Last 100 events for the dashboard's terminal-style view
Auto-restart on boot tmux session managed by ~/.wsl-agent-autostart.sh for unattended uptime

Quality scoring rubric

Every lead gets a deterministic 0-100 score on every scan:

Signal Points (capped)
Posted < 24h ago +30
Posted < 72h ago +20
Posted < 7d ago +10
Body > 600 chars +25
Body > 200 chars +15
Body > 50 chars +5
Keyword match density +5/match (cap 20)
High-intent phrase ("willing to pay", "$", "hire", "need a") +5/match (cap 15)
HN post points > 5 +5
HN comments > 3 +5

Score 50+ is the auto-draft threshold (configurable). Anything below is held for manual review, never auto-replied.


REST API

Lead pipeline

Method Path Purpose
GET /api/leads List all leads
POST /api/leads/:id/status Update status (New / Drafted / Sent / Done)
POST /api/leads/:id/draft Set replyDraft manually
POST /api/leads/:id/ai-generate Generate AI draft via Gemini/OpenAI
POST /api/scraper/scan Trigger Reddit + HN scan manually
GET /api/leads/export.csv Download CSV (browser)
POST /api/leads/export Snapshot CSV to data/exports/

Webhook

Method Path Purpose
POST /api/webhooks/lemonsqueezy Receive order events, update analytics

Signature verification: HMAC SHA-256 header X-Signature against settings.lemonsqueezyWebhookSecret.

Other

Method Path Purpose
GET / POST /api/settings Runtime config
GET / POST / PUT /api/offers[/:id] Manage micro-offers
GET / POST /api/content Faceless content generation log
GET /api/analytics Funnel + revenue counters
POST /api/analytics/simulate-purchase Manual test purchase
GET /api/logs Last 100 in-memory log events
GET /offer/:slug Render offer landing page

Tech stack

  • Runtime: Node.js 18+
  • Framework: Express 4
  • Scraping: rss-parser (Reddit), Algolia public API (HN)
  • AI: Gemini (default), OpenAI (alternate)
  • Storage: JSON-on-disk (data/*.json) + per-day CSV snapshots
  • Webhooks: HMAC SHA-256 signature verification
  • Public exposure: Cloudflare Tunnel (free) for inbound webhook traffic
  • Process supervision: tmux + .bashrc-triggered autostart

The on-disk JSON store is intentional: this is a single-user system, the read/write rate is < 10 ops/sec, and the simplicity is a feature. If volume grows, the storage layer is one module (data/*.json accessors) and easy to swap for SQLite or Postgres.


Quick start

git clone <repo_url>
cd stealth-ai

npm install
node server.js
# Dashboard at http://localhost:3000

On first boot, all JSON databases self-seed with starter data. To run continuously:

# Detached tmux session
tmux new-session -d -s lead-discovery 'node server.js'

# Re-attach to view logs
tmux attach -t lead-discovery
# Ctrl+B then D to detach without killing it

Settings (data/settings.json)

Key Default Purpose
apiProvider gemini gemini or openai
apiKey (set) LLM API key
keywords (8 keywords) Comma-separated, case-insensitive matching
subreddits (8 subs) Comma-separated subreddit list
redditUserAgent (string) UA header for Reddit RSS
hackerNewsEnabled true Toggle HN Algolia scraper
autoDraftEnabled false Auto-generate drafts on scan
autoDraftMinScore 50 Quality threshold for auto-draft
lemonsqueezyWebhookSecret "" Signing secret from LS dashboard
checkoutLink "" Lemon Squeezy URL (override per-offer)

Webhook setup (production)

# 1. Tunnel local server to a public URL
cloudflared tunnel --url http://localhost:3000
# → note the https://*.trycloudflare.com URL

# 2. In Lemon Squeezy dashboard
#    Settings → Webhooks → Add endpoint
#    URL: https://*.trycloudflare.com/api/webhooks/lemonsqueezy
#    Events: order_created (minimum)
#    Copy the signing secret

# 3. Save the secret
curl -X POST http://localhost:3000/api/settings \
  -H "Content-Type: application/json" \
  -d '{"lemonsqueezyWebhookSecret": "ls_whsec_..."}'

# 4. Make a test purchase, then verify
tmux attach -t lead-discovery
# Look for "LS webhook: order ... confirmed."

Project layout

stealth-ai/
├── server.js                  # Express app, routes, scheduler
├── lib/
│   ├── hn-scraper.js          # Hacker News Algolia client
│   ├── lead-utils.js          # Dedupe + 0-100 quality scoring
│   ├── csv-export.js          # RFC 4180 CSV writer
│   └── webhook.js             # LS HMAC verification + order parser
├── public/                    # Static dashboard (vanilla JS + CSS)
│   ├── index.html
│   ├── app.js
│   ├── style.css
│   └── offer-template.html    # Server-rendered landing page
├── data/                      # JSON persistence (gitignored)
│   ├── settings.json
│   ├── leads.json
│   ├── offers.json
│   ├── content.json
│   ├── analytics.json
│   └── exports/
└── package.json

Operations cheatsheet

# Live log tail
tmux attach -t lead-discovery

# Trigger scan now
curl -X POST http://localhost:3000/api/scraper/scan

# Export CSV
curl -X POST http://localhost:3000/api/leads/export
curl  http://localhost:3000/api/leads/export.csv -o leads.csv

# Restart cleanly
tmux kill-session -t lead-discovery
cd ~/stealth-ai && tmux new-session -d -s lead-discovery 'node server.js'

# Syntax check before reboot
node -c server.js

What this project taught me

  • Designing scoring heuristics that survive contact with messy real-world text
  • Building webhook receivers correctly (HMAC verification, idempotency, replay safety)
  • Running a long-lived Node.js service on a single laptop without losing data
  • Letting AI write drafts without letting it post — keeping humans in the qualification loop
  • Wiring discovery → qualification → outreach → checkout → analytics into one observable loop

Roadmap

  • Reddit + HN multi-source scraping
  • 0-100 quality scoring
  • AI draft generation (Gemini + OpenAI)
  • Lemon Squeezy webhook integration
  • Daily CSV snapshots
  • LinkedIn + IndieHackers scrapers
  • Per-niche scoring profiles
  • Postgres migration (when JSON file grows past ~5MB)
  • Multi-user mode with auth

Status & disclaimer

  • Status: Active. Running on a developer laptop with daily Cloudflare Tunnel exposure for webhook reception.
  • Disclaimer: This is a personal automation system, not a hosted SaaS. All AI drafts are human-reviewed before posting. The system follows each platform's API and content rules.
  • Privacy: No PII is scraped beyond what is publicly posted. No emails are sent without explicit human action.

Author

Built solo by @akwsa. Open to remote roles in Backend Engineering · Machine Learning · AI Automation. Based in Indonesia (UTC+7), full-time available.

Reach out via LinkedIn or email — see profile.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors