How this is built
Stack, data wiring, and how to point the panel at live Airtable.
What you're looking at
The MEGATRON control panel — the command center for LVE's autonomous cold-outreach pipeline. MEGATRON discovers trade shows, scores them (timing → exhibitor count → warehouse proximity), scrapes and enriches every exhibitor into a scored lead, runs a 5-email sequence in Megan's voice, and detects replies and booked calls. The Attribution view traces that whole funnel; every win is tagged source: MEGATRON and traceable to its show and campaign.
Stack
Next.js 14 (App Router, server components) · Tailwind with a custom token system · Recharts for trends · Geist for UI, Geist Mono for every number. Light monochrome throughout: white surfaces, zinc hairlines, black reserved for emphasis — a booked call is the only solid-black element on any screen.
Data flows through one server-side module (lib/data.ts): live Airtable when a key is present, rich deterministic seed data otherwise. The API routes /api/shows, /api/exhibitors and /api/config keep the same response contract as the production panel.
Pointing it at live Airtable
One env var flips the whole panel from seed to live. Nothing else changes:
# Vercel → Project → Settings → Environment Variables AIRTABLE_API_KEY=pat_xxx # required — a read-scoped personal access token AIRTABLE_BASE_ID=appccQu8ED41C4Som # optional, this is the default # table overrides (optional, these are the defaults) AIRTABLE_SHOWS_TABLE=tblSlCLJDY4m5QKz3 AIRTABLE_LEADS_TABLE=tblnde3kiJD6dgyDL
The reader paginates the full tables server-side (the key never reaches the browser), caches for 60s, and binds to the exact production field names — Show Key, Outreach, Score Breakdown, Brand File, etc. If Airtable is unreachable it falls back to seed rather than rendering a dead panel.
One approximation in live mode: the trend chart buckets events by each lead's Updated timestamp (Airtable stores status, not an event log). Seed mode simulates a precise send/reply/book log. For exact live trends, point a small webhook at Smartlead/Calendly events — the production panel already receives both.
The funnel, mapped to data
Shows discovered all SHOWS rows
Shows active Pipeline Status = "Active"
Exhibitors scraped all LEADS rows
Reachable leads Score > 0 (no reachable contact → hard-gated to 0)
In outreach Outreach ∈ {Queued, Sent, Replied, Booked}
Sent Outreach ∈ {Sent, Replied, Booked}
Replied ★ Outreach ∈ {Replied, Booked}
Booked ★★ Outreach = "Booked"
Drop-off Outreach ∈ {Bounced, Suppressed}Per-show attribution groups leads by Show Key and counts wins — that's the ROI-by-show table on the dashboard.
Deploy notes
This is a standalone preview deployment — deliberately separate from the production control-panel project, whose webhook endpoints (/api/calendly-webhook, /api/smartlead-webhook) a running pipeline depends on. To migrate this UI into production: copy app/, components/ and lib/ over, keep the existing webhook + mutate routes untouched, and carry the tailwind.config.ts + globals.css token system.
Design system, briefly
Monochrome engineering-paper: white surfaces with zinc hairline borders (--floor → --booth → --booth-2), registration ticks crossing card corners, ink in four gray steps. Color is rationed to meaning — green and red exist only as deltas and failure states; conversion is carried by black: Replied takes the ink outline, Booked is the one solid-black chip in the interface. Charts render in textures (slatted bars, dashed lines) instead of hues. Numbers are always mono and tabular so nothing shifts as data updates.