Production-ready lead-generation and strict qualification engine for DLX Designs — a luxury bespoke traditional menswear brand targeting high-net-worth clients, grooms and corporate executives in Lagos & Abeokuta, Nigeria.
It ingests real inbound traffic, filters out low-budget seekers with strict semantic rules, stores only verified high-intent leads, and renders them as scored lead cards in a live dashboard.
Live dashboard: Try the app Ingest endpoint:
POST /api/ingest
Rendering mermaid diagram...
Runs in backend/worker/qualifier.ts and never fabricates data.
Layer 1 — hard disqualifiers (instant reject): cheap, affordable,
under 20k/20k, discount, thrift, okirika.
Layer 2 — scoring matrix (0–100): baseline 25, high-tier signals add points —
bespoke +18, groom/chieftaincy +20, cashmere +15, wedding +14,
3-piece +12, executive +14, lekki/victoria island +10, lagos/abeokuta
+6, etc. Pass threshold: ≥ 50. Sub-threshold leads are rejected.
Layer 3 — AI refinement (optional, zero-config by default): the engine is
deterministic-first — the strict heuristic above is authoritative and needs
no AI key, no external call, no cost, so no provider can ever block it. If
you add a free-tier key, that provider refines the score and writes a natural
buying signal (tried in order: GEMINI_API_KEY, GROQ_API_KEY, OPENAI_API_KEY).
A provider failing just falls back to the heuristic — never an error.
| Method | Path | Purpose |
|---|---|---|
GET | / | Dashboard |
GET | /dashboard | Dashboard (alias) |
GET | /api/leads | Verified leads (JSON, strongest first) |
POST | /api/ingest | Ingest & qualify an inbound lead — 201 on pass, 422 on reject |
POST | /api/leads/:id/status | Advance pipeline stage (or set one) — records history |
GET | /api/analytics | Pipeline / source / signal analytics (the learn layer) |
POST /api/ingest request body:
{ "name": "Oluwatosin Adeyemi", "gmail": "tosin@example.com", "source": "nigerianmenswear.com", "message": "I need a bespoke 3-piece groom suit for my chieftaincy ceremony in Abeokuta" }
Only passing leads persist. Rejected and duplicate leads are returned (422) and never stored.
A verified lead is more than a row — it is a story with evidence:
cron/hunt.ts polls a real configured source (DLX_HUNT_URL)
and feeds genuinely captured inquiries through the qualifier. It never
invents people or signals; rows without evidence are ignored.source, source_url),
exactly what was said (evidence), and when (created_at).action, chosen from the actual signal:
book consultation, contact to confirm budget, or nurture.new → qualified → contacted → responded → consultation → quoted → deposit_paid → ordered → won/lost. Every transition
is recorded in history./api/analytics reports conversion by stage and top sources and
signals that actually produce qualified opportunities.Option A — website ingestion. A ready, branded enquiry form is hosted at
/capture (or embedded by iframing it). It posts each submission to
/api/ingest, which qualifies and stores it. Direct API for a custom site:
POST https://dlx-leads.val.run/api/ingest Content-Type: application/json { "name": "…", "gmail": "…", "phone": "…", "message": "…", "source": "…", "source_url": "…" }
Option C — JSON / Google Sheet feed (autonomous, scheduled every 15 min). The hunt poller accepts a published Google Sheet CSV directly, no code:
gmail (plus optional
name, phone, message, source, source_url).DLX_HUNT_URL (and DLX_HUNT_TOKEN if it's private/behind auth).Each run, the engine ingests every new row, qualifies it, and skips duplicates. Rows without an email are ignored — nothing is invented.
Option B — email intake (live inbound hunting). Forward any organic inquiry (DM, WhatsApp, web message, marketplace lead) to the engine's email address and it is qualified, evidence-tagged, and tracked automatically:
dlxdesigns-e7b272d2a81611f19be51607ee4eb77e@valtown.email
See docs/growth-corridors.md for the 50-verified
growth corridors (marketplaces, fashion platforms, directories, fashion-week
hubs, forums, and press) — each mapped to an acquisition, observation, or
partnership role the engine can consume.
The engine side is built and tested. To connect Meta (one-time, your login):
instagram_business_basic, instagram_business_manage_messages,
and pages_messaging permissions (a long-lived User or Page token).https://dlx-leads.val.run/api/instagram/webhook
using your INSTAGRAM_VERIFY_TOKEN as the verify token.Real DMs/comments then push into the engine automatically. Because Instagram
DMs carry no email, each becomes a signal (/api/signals); reply to capture
the email, then promote it to a verified lead with
POST /api/signals/:id/promote.
Reviews, Q&A, and "do you make…" messages on your Google Business Profile are
high-intent local signals. Capture them in one call — they become scored
prospects source-tagged google-business-profile in the Command Center, ready
to draft and convert:
POST https://dlx-leads.val.run/api/gbp Content-Type: application/json { "reviewer": "Adaeze Okafor", "message": "Do you make bespoke 3-piece groom suits for Lagos weddings?", "email": "…", "phone": "…", "permalink": "https://maps.google.com/…" }
Manual route (no credentials): a VA or owner copies each new review/Q&A/message
and posts it to /api/gbp (or the dashboard capture form with
source: google-business-profile), and the automaton takes it from there.
Automated pull of your GBP inbox requires Google OAuth on your account — that
part is yours to connect when ready; everything after capture is handled here.
Everything runs out of the box with zero environment variables. The qualification engine is fully deterministic. The following optional keys unlock the AI refinement layer (free tiers are preferred — none require billing) and the Supabase mirror:
GEMINI_API_KEY — free tier (Google AI Studio key, no card required). Recommended.GROQ_API_KEY — free tier. Ignored unless Gemini is absent or fails.OPENAI_API_KEY — requires active OpenAI billing; only used as a last resort.SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY — mirror verified leads to
your Supabase dlx_verified_leads table (native SQLite store stays authoritative).DLX_HUNT_URL — JSON or published-CSV feed the hunt poller watches
for genuine inquiries (JSON: { "leads": [ { name, gmail, phone, message, source, source_url } ] }).DLX_HUNT_TOKEN — optional bearer token sent to the hunt source (Authorization: Bearer …).INSTAGRAM_VERIFY_TOKEN — random string you invent; Meta must echo it on webhook verification.META_APP_SECRET — optional; enables X-Hub-Signature-256 verification on Instagram webhooks.DLX_BRAND_NAME — whitelabel brand shown in capture copy + drafts (default: DLX Designs).ENABLE_AUTOSEND — set to 1 to let the nurture automaton actually email first touches; OFF (dry-run) by default.👉 Add GEMINI_API_KEY here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=GEMINI_API_KEY 👉 Add GROQ_API_KEY here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=GROQ_API_KEY 👉 Add OPENAI_API_KEY here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=OPENAI_API_KEY 👉 Add SUPABASE_URL here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=SUPABASE_URL 👉 Add SUPABASE_SERVICE_ROLE_KEY here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=SUPABASE_SERVICE_ROLE_KEY 👉 Add DLX_HUNT_URL here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=DLX_HUNT_URL 👉 Add DLX_HUNT_TOKEN here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=DLX_HUNT_TOKEN 👉 Add INSTAGRAM_VERIFY_TOKEN here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=INSTAGRAM_VERIFY_TOKEN 👉 Add META_APP_SECRET here: https://www.val.town/x/dlxdesigns/dlx-lead-engine/environment-variables?key=META_APP_SECRET
Create the mirror table by running database/schema.sql
in the Supabase SQL editor. The table uses gen_random_uuid() ids, enforces a
score BETWEEN 0 AND 100 check, has a gmail UNIQUE constraint, and enables
Row-Level Security (locked to service-role access by default). The val writes
via PostgREST with the service-role key and resolution=merge-duplicates.
database/
schema.sql ← Supabase/PostgreSQL schema (mirror table)
backend/
config.ts ← whitelabel brand + runtime config
pipeline.ts ← sales pipeline stages + next-stage logic
hunt.ts ← autonomous ingestion from a real configured source
outbound.ts ← prospect queue: score, auto-draft, guarded send, convert
instagram.ts ← Meta webhook receiver for real IG DMs/comments
worker/
qualifier.ts ← strict qualification engine (disqualifiers + scoring)
ingest.ts ← ingest worker (bridge inbound → store)
llm.ts ← optional AI adapter (free tier Gemini / Groq / OpenAI)
cron/
hunt.ts ← scheduled hunt poller (every 15 min)
automate.ts ← nurture automaton: nudge hot leads + auto-send (guarded)
email/
lead-intake.ts ← email-triggered lead intake (forward inquiries here)
docs/
growth-corridors.md ← 50 acquisition/observation/partnership corridors
operating-model.md ← how the automaton runs + per-client deployment model
lib/
store.ts ← SQLite persistence + Supabase mirror + pipeline + analytics
frontend/
components/App.tsx ← dashboard layout + empty state + pipeline strip
components/LeadCard.tsx ← verified-lead card with evidence, action & stage
components/LeadForm.tsx ← inline lead-capture form
scripts/
selftest.ts ← end-to-end qualifier + store self-test
index.ts ← Hono HTTP backend (dashboard + /api/*)
POST /api/ingest submission that passed strict qualification.scripts/selftest.ts exercises the full pipeline with synthetic example inputs
(high-intent pass, low-budget reject, no-signal reject, duplicate reject) and is
safe to run repeatedly.