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...
- Dashboard: client-side React + Hono backend (App Router-equivalent), Twind/Tailwind styling.
- Database: val-scoped PostgreSQL-compatible SQLite. Supabase mirror optional.
- Qualifier: deterministic heuristic (zero-config) + optional free-tier AI refinement.
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:
- Hunt —
cron/hunt.tspolls 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. - Verify — every lead records where it came from (
source,source_url), exactly what was said (evidence), and when (created_at). - Qualify — strict scoring (0–100); only ≥ 50 passes.
- Prioritize — the dashboard sorts strongest first and shows live pipeline counts.
- Recommend — each lead carries a
action, chosen from the actual signal: book consultation, contact to confirm budget, or nurture. - Track — leads move through
new → qualified → contacted → responded → consultation → quoted → deposit_paid → ordered → won/lost. Every transition is recorded inhistory. - Learn —
/api/analyticsreports 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:
- In your sheet, make row 1 a header that includes
gmail(plus optionalname,phone,message,source,source_url). - File → Share → Publish to web → choose the sheet → format CSV → copy the link.
- Set that link as
DLX_HUNT_URL(andDLX_HUNT_TOKENif 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):
- Create a Meta for Developers app (https://developers.facebook.com).
- Add the Instagram product and connect your Instagram Business account.
- Create a token with the
instagram_business_basic,instagram_business_manage_messages, andpages_messagingpermissions (a long-lived User or Page token). - Set these on the val: 👉 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
- In Meta → Developer App → Webhooks, subscribe the Instagram object to
the callback URL:
https://dlx-leads.val.run/api/instagram/webhookusing 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 Supabasedlx_verified_leadstable (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; enablesX-Hub-Signature-256verification on Instagram webhooks.DLX_BRAND_NAME— whitelabel brand shown in capture copy + drafts (default:DLX Designs).ENABLE_AUTOSEND— set to1to 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/*)
- No hardcoded, fake, or mock contacts anywhere. Every record comes from a
real
POST /api/ingestsubmission that passed strict qualification. - Empty store → dashboard shows “Awaiting live inbound high-intent signals…”, never fake cards.
- Duplicate emails are rejected (UNIQUE), budget seekers are dropped, sub-50 intent is dropped.
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.