Autonomous Outbound. Zero Humans. Infinite Scale.
Dashboard for a 5-phase autonomous AI sales pipeline. The dashboard does not run the AI pipeline itself — the pipeline runs in n8n and writes results into Airtable. This app:
- Adds a lead via a form → fires a webhook to n8n.
- Polls Airtable in real time and displays results the moment they land.
- Provides a live "watch-it-populate" detail view per lead.
npm install
npm run devThen open the URL Vite prints (default http://localhost:5173) and log in with shiv / shiv.
Credentials are already wired in .env. If you need to change them:
| Variable | Purpose |
|---|---|
VITE_AIRTABLE_PAT |
Personal Access Token with read access to the leads base. |
VITE_AIRTABLE_BASE_ID |
Base ID (appafVmMyC9doWgnW). |
VITE_AIRTABLE_TABLE_ID |
Table ID (tbln9n7qD87K6Wozv). |
VITE_N8N_WEBHOOK_URL |
The /webhook/add-lead endpoint on your n8n instance. |
The app is read-only against Airtable. n8n owns all writes.
- Log in with
shiv/shiv. - Dashboard — KPIs, pipeline-by-stage chart, score donut, and a live table of recent leads.
- Add Lead → fill the form → "Launch Pipeline". The webhook fires n8n, the launch modal shows the 5 phases, and the app polls Airtable by phone every 2 seconds.
- As soon as the record appears, you're routed to Lead Detail, where every card populates progressively:
- Profile (LinkedIn + PDL)
- LinkedIn post research
- Perplexity online research
- Call summary, pain points, key moments, next steps
- WhatsApp opener + personalised video
- Pipeline — real-time kanban view across New / Researching / Called / Qualified / Closed.
- React 18 + Vite — framework + dev server.
- Tailwind CSS 3 — styling, brand tokens in
tailwind.config.js. - React Router v6 — routing.
- framer-motion — page and card animations.
- recharts — dashboard charts.
- lucide-react — icons.
src/lib/airtable.js—fetchList,fetchRecord,fetchByPhone.src/lib/webhook.js—triggerAddLead(payload)→ POST to n8n.src/hooks/useAirtableList.js— polls list every 5s, detects changed records.src/hooks/useAirtableRecord.js— polls a single record every 2s (fast window 3min), then 5s.src/hooks/usePollingVisibility.js— pauses polling when the tab is hidden.
- Pauses automatically when the tab is hidden, resumes on focus.
- Backs off on 429 to 10s, then recovers.
- Stops on 401 (auth failure).
- Retries transient network failures with exponential backoff (2s → 16s cap).
- Newly populated fields fade-in and pulse a subtle teal border for 800ms.
- Skeleton shimmers hold space before data arrives — no layout shift.
- The Enrichment Progress stepper lights up each phase as its Airtable fields populate.
Airtable column names are case-sensitive and come directly from the spec. See src/config/fieldMap.js for the full list. Notable:
linkedin Posts Summary— lowercaselon purpose.Summary of Perplexity research— long-text research output.Pipeline Stage—New | Researching | Called | Qualified | Closed.
- Dark mode only — no light-mode leakage, no toggle.
- No mock data: if Airtable is empty, empty states show.
- The SaaS never writes to Airtable. Only reads.