666 lines
26 KiB
Markdown
666 lines
26 KiB
Markdown
# CloseBot SMS — Definitive Build Plan
|
|
|
|
> Unified app: Twilio native SMS + CloseBot AI bots. One dashboard to rule them all.
|
|
|
|
---
|
|
|
|
## 1. TECH STACK
|
|
|
|
| Layer | Technology | Why |
|
|
|---|---|---|
|
|
| **Frontend** | Next.js 14 (App Router) + Tailwind CSS + shadcn/ui | Dark-mode-first, server components, fast |
|
|
| **Backend** | Next.js API routes (Edge-compatible) | Same deployment, zero CORS |
|
|
| **Database** | SQLite via better-sqlite3 (dev) → Turso/LibSQL (prod) | State tracking, conversation history, routing config |
|
|
| **Real-time** | Server-Sent Events (SSE) | Live conversation updates on dashboard |
|
|
| **SMS** | Twilio Node SDK (`twilio`) | Send/receive SMS, delivery status |
|
|
| **AI Bots** | CloseBot API (direct HTTP) | Webhook Source for inbound, API for bots/leads/metrics |
|
|
| **Auth** | NextAuth.js with credentials provider | Simple login, protect all routes |
|
|
| **Deploy** | Railway / Fly.io / Vercel | Needs persistent process for webhooks |
|
|
|
|
---
|
|
|
|
## 2. SYSTEM ARCHITECTURE
|
|
|
|
```
|
|
┌─────────────┐ ┌──────────────────────────┐ ┌─────────────┐
|
|
│ Customer │────>│ Twilio (SMS) │────>│ CloseBot │
|
|
│ Phone │<────│ │<────│ SMS App │
|
|
└─────────────┘ └──────────────────────────┘ └──────┬──────┘
|
|
│
|
|
┌──────────────────────────┐ │
|
|
│ CloseBot API │<───────────┘
|
|
│ (Webhook Source) │────────────┐
|
|
└──────────────────────────┘ │
|
|
v
|
|
┌──────────────┐
|
|
│ SQLite DB │
|
|
│ (state/logs) │
|
|
└──────────────┘
|
|
```
|
|
|
|
**Message Flow — Inbound:**
|
|
1. Customer sends SMS to Twilio number
|
|
2. Twilio POSTs to `POST /api/webhooks/twilio/inbound`
|
|
3. App looks up routing: which Twilio number → which CloseBot bot/source
|
|
4. App sends inbound event to CloseBot via `POST /webhook/event/{sourceId}` with:
|
|
- `type: "message"`
|
|
- `contactId` (phone number as unique identifier)
|
|
- `message` (SMS body)
|
|
- `state` (JSON: `{ twilioNumber, phoneFrom, messageSid }`)
|
|
5. CloseBot processes through bot flow
|
|
6. CloseBot POSTs response to our webhook retrieval URL: `POST /api/webhooks/closebot/response`
|
|
7. App receives response, extracts `state` to get the Twilio number + customer phone
|
|
8. App sends SMS via Twilio API
|
|
9. App logs everything to SQLite + broadcasts via SSE for live dashboard
|
|
|
|
**Message Flow — Manual Override (from Conversations view):**
|
|
1. User types message in the conversation UI
|
|
2. App sends SMS directly via Twilio (bypassing CloseBot)
|
|
3. Logs to SQLite with `source: "manual"` flag
|
|
|
|
---
|
|
|
|
## 3. DATABASE SCHEMA
|
|
|
|
```sql
|
|
-- Routes: Twilio number → CloseBot bot mapping
|
|
CREATE TABLE routes (
|
|
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(8)))),
|
|
twilio_number TEXT NOT NULL UNIQUE,
|
|
twilio_number_sid TEXT,
|
|
closebot_source_id TEXT NOT NULL,
|
|
closebot_bot_id TEXT,
|
|
bot_name TEXT,
|
|
greeting_message TEXT,
|
|
after_hours_reply TEXT,
|
|
business_hours_json TEXT, -- {"mon": {"start": "09:00", "end": "17:00"}, ...}
|
|
max_concurrent INTEGER DEFAULT 50,
|
|
active BOOLEAN DEFAULT TRUE,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Contacts: phone numbers we've interacted with
|
|
CREATE TABLE contacts (
|
|
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(8)))),
|
|
phone TEXT NOT NULL UNIQUE,
|
|
name TEXT,
|
|
email TEXT,
|
|
status TEXT DEFAULT 'new', -- new, active, qualified, booked, closed, cold
|
|
closebot_lead_id TEXT,
|
|
assigned_bot_id TEXT,
|
|
assigned_route_id TEXT REFERENCES routes(id),
|
|
tags TEXT, -- JSON array
|
|
fields_json TEXT, -- collected fields from CloseBot
|
|
first_contact DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
last_contact DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
message_count INTEGER DEFAULT 0
|
|
);
|
|
|
|
-- Messages: every SMS in/out
|
|
CREATE TABLE messages (
|
|
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(8)))),
|
|
contact_id TEXT REFERENCES contacts(id),
|
|
route_id TEXT REFERENCES routes(id),
|
|
direction TEXT NOT NULL, -- 'inbound' | 'outbound'
|
|
source TEXT NOT NULL, -- 'customer' | 'bot' | 'manual'
|
|
body TEXT NOT NULL,
|
|
twilio_sid TEXT,
|
|
twilio_status TEXT, -- queued, sent, delivered, failed, undelivered
|
|
closebot_message_id TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Settings: app-wide config
|
|
CREATE TABLE settings (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Events: activity log for dashboard feed
|
|
CREATE TABLE events (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
type TEXT NOT NULL, -- 'message_in', 'message_out', 'booking', 'new_lead', 'status_change'
|
|
contact_id TEXT REFERENCES contacts(id),
|
|
route_id TEXT REFERENCES routes(id),
|
|
data_json TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 4. API ROUTES
|
|
|
|
### Webhook Endpoints (public, Twilio/CloseBot call these)
|
|
| Route | Method | Purpose |
|
|
|---|---|---|
|
|
| `/api/webhooks/twilio/inbound` | POST | Receive inbound SMS from Twilio |
|
|
| `/api/webhooks/twilio/status` | POST | Receive delivery status updates |
|
|
| `/api/webhooks/closebot/response` | POST | Receive CloseBot bot responses |
|
|
|
|
### Internal API (authenticated, frontend calls these)
|
|
| Route | Method | Purpose |
|
|
|---|---|---|
|
|
| `/api/dashboard/stats` | GET | Active convos, messages today, bookings, response rate |
|
|
| `/api/dashboard/activity` | GET | Recent activity feed (SSE endpoint) |
|
|
| `/api/conversations` | GET | List conversations with pagination/filters |
|
|
| `/api/conversations/[contactId]` | GET | Get single conversation with messages |
|
|
| `/api/conversations/[contactId]/send` | POST | Send manual SMS message |
|
|
| `/api/bots` | GET | List CloseBot bots (proxied from CloseBot API) |
|
|
| `/api/bots/[id]` | GET | Get bot details + metrics |
|
|
| `/api/contacts` | GET | List/search contacts with filters |
|
|
| `/api/contacts/[id]` | GET/PUT/DELETE | Contact CRUD |
|
|
| `/api/contacts/export` | GET | Export CSV |
|
|
| `/api/analytics/overview` | GET | Summary metrics with date range |
|
|
| `/api/analytics/messages` | GET | Message volume time series |
|
|
| `/api/analytics/bots` | GET | Per-bot conversation counts |
|
|
| `/api/analytics/outcomes` | GET | Outcome distribution |
|
|
| `/api/analytics/leaderboard` | GET | Top performing bots |
|
|
| `/api/routes` | GET/POST | List routes, create new route |
|
|
| `/api/routes/[id]` | GET/PUT/DELETE | Route CRUD |
|
|
| `/api/settings` | GET/PUT | App settings (Twilio creds, CloseBot key) |
|
|
| `/api/settings/test-connection` | POST | Test Twilio + CloseBot connections |
|
|
|
|
---
|
|
|
|
## 5. PAGE-BY-PAGE UI SPEC
|
|
|
|
### 5A. DASHBOARD (`/`)
|
|
**Matches mockup: closebot-sms-dashboard.png**
|
|
|
|
**Layout:**
|
|
- Left sidebar (240px): Logo "CloseBot SMS" + 6 nav items with icons
|
|
- Top bar: Global search input
|
|
- Main content area
|
|
|
|
**Components:**
|
|
1. **Stat Cards Row** — 4 cards in a grid
|
|
- Active Conversations (chat bubble icon, count from DB)
|
|
- Messages Today (envelope icon, count from DB where date = today)
|
|
- Bookings Made (calendar icon, from CloseBot metrics API)
|
|
- Response Rate (trending icon, calculated: bot_responses / inbound_messages * 100)
|
|
- Each card: dark glass-morphism background (`bg-slate-800/50 backdrop-blur`), cyan border glow, icon top-left, label + big number
|
|
|
|
2. **Real-time Activity Table**
|
|
- Columns: SMS (phone number), Bot Name, Badges (status pill), Timestamp
|
|
- Status pills: `active` (green), `pending` (yellow), `closed` (gray)
|
|
- Auto-updates via SSE — new rows slide in at top
|
|
- Click row → navigate to conversation
|
|
|
|
**Data sources:**
|
|
- Stats: `GET /api/dashboard/stats` → queries SQLite counts
|
|
- Activity: `GET /api/dashboard/activity` → SSE stream from events table
|
|
|
|
---
|
|
|
|
### 5B. CONVERSATIONS (`/conversations`)
|
|
**Matches mockup: closebot-sms-conversations.png**
|
|
|
|
**Layout:** Two-panel split (left 380px list, right flexible chat)
|
|
|
|
**Left Panel — Conversation List:**
|
|
- Search bar with filter icon + settings icon
|
|
- "All Filters" dropdown (by status, bot, date range)
|
|
- Conversation rows: avatar (generated from initials), name, phone, last message preview (truncated), timestamp, unread badge (cyan circle with count)
|
|
- Selected conversation highlighted with left cyan border
|
|
- Sorted by most recent message
|
|
|
|
**Right Panel — Chat Thread:**
|
|
- Header: avatar, name, phone number, "CloseBot SMS AI" badge, status dot + "Active" label
|
|
- Message bubbles:
|
|
- Inbound (customer): dark gray background (`bg-slate-700`), left-aligned with avatar
|
|
- Outbound (bot): cyan/blue gradient background, right-aligned
|
|
- Each bubble shows text, no timestamps on individual messages (clean look)
|
|
- Bottom: text input "Type a message..." with cyan send button
|
|
- Sending from here = manual override, bypasses CloseBot
|
|
|
|
**Data sources:**
|
|
- List: `GET /api/conversations?search=&status=&bot=&page=`
|
|
- Messages: `GET /api/conversations/[contactId]`
|
|
- Send: `POST /api/conversations/[contactId]/send`
|
|
- Live updates: SSE for new messages appended to thread
|
|
|
|
---
|
|
|
|
### 5C. BOTS (`/bots`)
|
|
**Matches mockup: closebot-sms-bots.png**
|
|
|
|
**Layout:** Grid of bot cards (3 columns on desktop)
|
|
|
|
**Top Bar:**
|
|
- "Bot Management" heading
|
|
- Search bots input + filter icon + sort icon
|
|
- "+ Create New Bot" button (cyan, calls CloseBot create_bot_with_ai)
|
|
|
|
**Bot Cards:**
|
|
- Card header: bot name in bold, gradient top border (different colors per bot)
|
|
- Fields: Status toggle (Active/Inactive), Twilio # (from route mapping), Messages count, Conversion % (from CloseBot metrics), Last Active
|
|
- Inactive bots appear dimmed/grayed
|
|
- Click expand chevron → expanded card shows:
|
|
- Connected Sources list
|
|
- Recent Performance sparkline (mini chart, last 7 days)
|
|
- "Edit Flow" button (opens CloseBot dashboard in new tab)
|
|
|
|
**Data sources:**
|
|
- Bots list: `GET /api/bots` → proxies CloseBot `GET /bot` + merges route data from SQLite
|
|
- Metrics: CloseBot `GET /botMetric/agencySummary`
|
|
- Toggle active: `PUT /api/routes/[id]` to enable/disable route
|
|
|
|
---
|
|
|
|
### 5D. CONTACTS (`/contacts`)
|
|
**Matches mockup: closebot-sms-contacts.png**
|
|
|
|
**Layout:** Full-width data table with optional slide-out detail panel
|
|
|
|
**Top Bar:**
|
|
- Search input
|
|
- Filter dropdowns: "Filter by Status" (hot/warm/cold/new), "Filter by Bot", date range picker
|
|
- "Import Contacts" button (cyan outline) + "Export CSV" button (cyan outline)
|
|
|
|
**Table Columns:**
|
|
- Name (bold)
|
|
- Phone Number
|
|
- Assigned Bot
|
|
- Status (colored dot: red=Hot Lead, orange=Warm, gray=Cold + text label)
|
|
- Messages Exchanged (number)
|
|
- Last Contact (relative time: "2 hours ago", "Yesterday")
|
|
- Tags (colored pills)
|
|
|
|
**Slide-out Detail Panel (on row click):**
|
|
- Contact name (large, bold)
|
|
- Phone, Email, Company fields
|
|
- "Conversation Summary" section — AI-generated from CloseBot
|
|
- Bullet points: "Product Interest", "Budget Discussion", etc.
|
|
- "Field Values Collected" — mini table of CloseBot-collected fields (Company Size, Industry, Priority)
|
|
- Action buttons: "View Full History" + "Send Message" (cyan)
|
|
|
|
**Data sources:**
|
|
- Table: `GET /api/contacts?search=&status=&bot=&dateFrom=&dateTo=&page=&limit=`
|
|
- Detail: `GET /api/contacts/[id]`
|
|
- Export: `GET /api/contacts/export` → CSV download
|
|
- Import: `POST /api/contacts/import` (CSV upload, creates contacts + optionally sends first message)
|
|
|
|
---
|
|
|
|
### 5E. ANALYTICS (`/analytics`)
|
|
**Matches mockup: closebot-sms-analytics.png**
|
|
|
|
**Layout:** Scrollable dashboard with multiple chart sections
|
|
|
|
**Top Bar:**
|
|
- "Analytics" heading
|
|
- Tab navigation: Dashboard, Conversations, Bots, Contacts, Settings
|
|
- Date range picker dropdown (top right): "Last 30 Days (Oct 1 - Oct 30, 2024)"
|
|
|
|
**Section 1 — Stat Cards (4 across):**
|
|
- Total Conversations (large number + sparkline + % change vs last period)
|
|
- Booking Rate (percentage + sparkline + change)
|
|
- Avg Response Time (duration format "1m 45s" + sparkline + change)
|
|
- Customer Satisfaction (rating "4.8/5" + sparkline + change)
|
|
- Each card has colored gradient background (red→pink, green, blue, purple)
|
|
|
|
**Section 2 — Messages Over Time (full width):**
|
|
- Line chart with dual lines: Inbound (blue) vs Outbound (green)
|
|
- X-axis: dates over selected range
|
|
- Y-axis: message count
|
|
- Tooltip on hover showing exact values
|
|
- Chart library: Recharts (React-native, works with Next.js)
|
|
|
|
**Section 3 — Two charts side by side:**
|
|
- Left: "Conversations by Bot" — horizontal bar chart with colored bars per bot
|
|
- Right: "Outcome Distribution" — donut chart with segments (Booked 40%, Qualified 30%, Dropped 18%, Pending 12%), total in center
|
|
|
|
**Section 4 — Top Performing Bots:**
|
|
- Mini leaderboard table: Rank, Bot Name (with icon), Conversations, Booking Rate, CSAT Score
|
|
- Sorted by booking rate descending
|
|
|
|
**Data sources:**
|
|
- Stats: `GET /api/analytics/overview?start=&end=`
|
|
- Messages chart: `GET /api/analytics/messages?start=&end=&resolution=daily`
|
|
- By bot: `GET /api/analytics/bots?start=&end=`
|
|
- Outcomes: `GET /api/analytics/outcomes?start=&end=`
|
|
- Leaderboard: `GET /api/analytics/leaderboard?start=&end=`
|
|
- All backed by SQLite queries (message counts, conversation outcomes) + CloseBot metrics API for bookings/CSAT
|
|
|
|
---
|
|
|
|
### 5F. ROUTING (`/routing`)
|
|
**Matches mockup: closebot-sms-routing.png**
|
|
|
|
**Layout:** Three-column visual routing display
|
|
|
|
**Top Bar:**
|
|
- Breadcrumb: "Routing / Phone Number Routing"
|
|
- Top nav tabs: Dashboard, Routing, Bots, Analytics, Settings
|
|
- "+ Add New Route" button (top right)
|
|
- Search bar + filter icon
|
|
|
|
**Three Columns:**
|
|
- **Left: Twilio Phone Numbers** — list of phone number cards with phone icon
|
|
- **Center: Routing** — animated connection lines (CSS/SVG) linking numbers to bots
|
|
- **Right: CloseBot Bots & Sources** — bot cards with: name, source badge (WEB_LEAD, EMAIL_INQUIRY, etc.), Active/Paused toggle, message count badge, "Configure" button
|
|
|
|
**Expanded Route Configuration (on Configure click):**
|
|
- Modal/drawer overlaying the route:
|
|
- Greeting Message Override (textarea, optional)
|
|
- After-Hours Auto-Reply Text (textarea)
|
|
- Business Hours Schedule — day-of-week toggle grid (Mon-Sun), time range "Mon-Fri: 9:00 AM - 5:00 PM", "Add Exception" link
|
|
- Max Concurrent Conversations — slider (1-100) with current value displayed
|
|
- Save + Close Configuration buttons
|
|
|
|
**Data sources:**
|
|
- Routes: `GET /api/routes` → SQLite routes table
|
|
- Twilio numbers: fetched from Twilio API on settings save, cached
|
|
- Bots: `GET /api/bots` → CloseBot API
|
|
- Update: `PUT /api/routes/[id]` with config JSON
|
|
|
|
---
|
|
|
|
### 5G. SETTINGS (`/settings`)
|
|
**Matches mockup: closebot-sms-settings.png**
|
|
|
|
**Layout:** Two-column card layout
|
|
|
|
**Cards:**
|
|
1. **Twilio Connection** — Account SID input (masked), Auth Token input (masked), "Connection Status" indicator (green dot + "Connected")
|
|
2. **CloseBot Connection** — API Key input (masked), Webhook Source ID (display), "Connection Status" indicator
|
|
3. **Phone Numbers** — list of Twilio numbers with assigned bot + toggle switch
|
|
4. **Notifications** — toggles: Email Alerts, SMS Delivery Failures, New Lead Alerts
|
|
5. **Webhook URLs** — read-only display of:
|
|
- Inbound URL (the URL you give to Twilio)
|
|
- Response URL (the URL you give to CloseBot Webhook Source)
|
|
- Copy buttons next to each
|
|
|
|
**Data sources:**
|
|
- Settings: `GET/PUT /api/settings`
|
|
- Test: `POST /api/settings/test-connection` → pings both APIs
|
|
|
|
---
|
|
|
|
## 6. FILE STRUCTURE
|
|
|
|
```
|
|
closebot-sms/
|
|
├── package.json
|
|
├── next.config.js
|
|
├── tailwind.config.ts
|
|
├── tsconfig.json
|
|
├── .env.local.example
|
|
├── BUILD_PLAN.md
|
|
├── README.md
|
|
├── prisma/ (or drizzle/)
|
|
│ └── schema.sql
|
|
├── src/
|
|
│ ├── app/
|
|
│ │ ├── layout.tsx # Root layout with sidebar
|
|
│ │ ├── page.tsx # Dashboard
|
|
│ │ ├── conversations/
|
|
│ │ │ └── page.tsx # Conversations split view
|
|
│ │ ├── bots/
|
|
│ │ │ └── page.tsx # Bot grid
|
|
│ │ ├── contacts/
|
|
│ │ │ └── page.tsx # Contacts table
|
|
│ │ ├── analytics/
|
|
│ │ │ └── page.tsx # Analytics dashboard
|
|
│ │ ├── routing/
|
|
│ │ │ └── page.tsx # Phone number routing
|
|
│ │ ├── settings/
|
|
│ │ │ └── page.tsx # Settings/config
|
|
│ │ └── api/
|
|
│ │ ├── webhooks/
|
|
│ │ │ ├── twilio/
|
|
│ │ │ │ ├── inbound/route.ts
|
|
│ │ │ │ └── status/route.ts
|
|
│ │ │ └── closebot/
|
|
│ │ │ └── response/route.ts
|
|
│ │ ├── dashboard/
|
|
│ │ │ ├── stats/route.ts
|
|
│ │ │ └── activity/route.ts # SSE
|
|
│ │ ├── conversations/
|
|
│ │ │ ├── route.ts
|
|
│ │ │ └── [contactId]/
|
|
│ │ │ ├── route.ts
|
|
│ │ │ └── send/route.ts
|
|
│ │ ├── bots/
|
|
│ │ │ ├── route.ts
|
|
│ │ │ └── [id]/route.ts
|
|
│ │ ├── contacts/
|
|
│ │ │ ├── route.ts
|
|
│ │ │ ├── export/route.ts
|
|
│ │ │ └── [id]/route.ts
|
|
│ │ ├── analytics/
|
|
│ │ │ ├── overview/route.ts
|
|
│ │ │ ├── messages/route.ts
|
|
│ │ │ ├── bots/route.ts
|
|
│ │ │ ├── outcomes/route.ts
|
|
│ │ │ └── leaderboard/route.ts
|
|
│ │ ├── routes/
|
|
│ │ │ ├── route.ts
|
|
│ │ │ └── [id]/route.ts
|
|
│ │ └── settings/
|
|
│ │ ├── route.ts
|
|
│ │ └── test-connection/route.ts
|
|
│ ├── components/
|
|
│ │ ├── layout/
|
|
│ │ │ ├── sidebar.tsx
|
|
│ │ │ ├── topbar.tsx
|
|
│ │ │ └── nav-item.tsx
|
|
│ │ ├── dashboard/
|
|
│ │ │ ├── stat-card.tsx
|
|
│ │ │ └── activity-feed.tsx
|
|
│ │ ├── conversations/
|
|
│ │ │ ├── conversation-list.tsx
|
|
│ │ │ ├── conversation-item.tsx
|
|
│ │ │ ├── chat-thread.tsx
|
|
│ │ │ ├── message-bubble.tsx
|
|
│ │ │ └── chat-input.tsx
|
|
│ │ ├── bots/
|
|
│ │ │ ├── bot-grid.tsx
|
|
│ │ │ └── bot-card.tsx
|
|
│ │ ├── contacts/
|
|
│ │ │ ├── contacts-table.tsx
|
|
│ │ │ ├── contact-detail-panel.tsx
|
|
│ │ │ └── contact-filters.tsx
|
|
│ │ ├── analytics/
|
|
│ │ │ ├── stat-card-sparkline.tsx
|
|
│ │ │ ├── messages-chart.tsx
|
|
│ │ │ ├── bots-bar-chart.tsx
|
|
│ │ │ ├── outcome-donut.tsx
|
|
│ │ │ └── bot-leaderboard.tsx
|
|
│ │ ├── routing/
|
|
│ │ │ ├── routing-view.tsx
|
|
│ │ │ ├── phone-number-card.tsx
|
|
│ │ │ ├── bot-route-card.tsx
|
|
│ │ │ ├── connection-lines.tsx # SVG animated lines
|
|
│ │ │ └── route-config-modal.tsx
|
|
│ │ └── settings/
|
|
│ │ ├── twilio-card.tsx
|
|
│ │ ├── closebot-card.tsx
|
|
│ │ ├── phone-numbers-card.tsx
|
|
│ │ ├── notifications-card.tsx
|
|
│ │ └── webhook-urls-card.tsx
|
|
│ ├── lib/
|
|
│ │ ├── db.ts # SQLite connection + queries
|
|
│ │ ├── twilio.ts # Twilio client wrapper
|
|
│ │ ├── closebot.ts # CloseBot API client (reuse from MCP server)
|
|
│ │ ├── sse.ts # SSE broadcast utility
|
|
│ │ └── utils.ts # Formatters, helpers
|
|
│ └── styles/
|
|
│ └── globals.css # Tailwind base + custom dark theme
|
|
```
|
|
|
|
---
|
|
|
|
## 7. DESIGN SYSTEM
|
|
|
|
**Colors (from mockups):**
|
|
```css
|
|
--bg-primary: #0f1729; /* deepest navy */
|
|
--bg-secondary: #1a2332; /* card backgrounds */
|
|
--bg-tertiary: #1e293b; /* elevated surfaces */
|
|
--bg-hover: #2d3748; /* table row hover */
|
|
--text-primary: #e2e8f0; /* main text */
|
|
--text-secondary: #94a3b8; /* muted text */
|
|
--text-muted: #64748b; /* timestamps, labels */
|
|
--accent-cyan: #22d3ee; /* primary accent */
|
|
--accent-blue: #3b82f6; /* secondary accent */
|
|
--accent-green: #22c55e; /* success, active */
|
|
--accent-yellow: #eab308; /* warning, pending */
|
|
--accent-red: #ef4444; /* error, hot lead */
|
|
--accent-orange: #f97316; /* warm */
|
|
--accent-purple: #a855f7; /* bot cards */
|
|
--border: #334155; /* subtle borders */
|
|
--border-glow: rgba(34, 211, 238, 0.2); /* cyan card glow */
|
|
```
|
|
|
|
**Typography:**
|
|
- Font: `Inter` (system-ui fallback)
|
|
- Headings: 600-700 weight
|
|
- Body: 400 weight
|
|
- Monospace numbers: `font-variant-numeric: tabular-nums`
|
|
|
|
**Card Style:**
|
|
```css
|
|
.card {
|
|
background: rgba(30, 41, 59, 0.5);
|
|
backdrop-filter: blur(12px);
|
|
border: 1px solid rgba(51, 65, 85, 0.5);
|
|
border-radius: 12px;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
|
}
|
|
```
|
|
|
|
**Status Badges:**
|
|
- Active: `bg-green-500/20 text-green-400 border-green-500/30`
|
|
- Pending: `bg-yellow-500/20 text-yellow-400 border-yellow-500/30`
|
|
- Closed: `bg-gray-500/20 text-gray-400 border-gray-500/30`
|
|
|
|
---
|
|
|
|
## 8. BUILD PHASES
|
|
|
|
### Phase 1 — Foundation (Day 1)
|
|
- [ ] Next.js project scaffold with Tailwind + shadcn/ui
|
|
- [ ] SQLite schema + db.ts with all queries
|
|
- [ ] Global layout with sidebar navigation (matches dashboard mockup)
|
|
- [ ] Dark theme CSS variables
|
|
- [ ] Environment config (.env.local)
|
|
- [ ] Twilio client wrapper
|
|
- [ ] CloseBot API client (port from closebot-mcp)
|
|
|
|
### Phase 2 — Core Webhook Bridge (Day 1-2)
|
|
- [ ] `POST /api/webhooks/twilio/inbound` — receive SMS, forward to CloseBot
|
|
- [ ] `POST /api/webhooks/closebot/response` — receive bot reply, send via Twilio
|
|
- [ ] `POST /api/webhooks/twilio/status` — delivery status updates
|
|
- [ ] Contact auto-creation on first inbound
|
|
- [ ] Message logging to SQLite
|
|
- [ ] Route lookup logic (Twilio number → CloseBot source)
|
|
- [ ] Business hours check + after-hours auto-reply
|
|
- [ ] State passthrough (phone + route info in CloseBot state field)
|
|
|
|
### Phase 3 — Dashboard + Real-time (Day 2)
|
|
- [ ] Dashboard page with 4 stat cards
|
|
- [ ] Real-time activity feed (SSE)
|
|
- [ ] Activity table with status badges
|
|
- [ ] Auto-refresh stats
|
|
|
|
### Phase 4 — Conversations (Day 2-3)
|
|
- [ ] Conversation list with search/filter
|
|
- [ ] Chat thread with message bubbles
|
|
- [ ] Manual message send
|
|
- [ ] Unread badges
|
|
- [ ] Live message updates via SSE
|
|
|
|
### Phase 5 — Bots + Contacts (Day 3)
|
|
- [ ] Bot grid with cards from CloseBot API
|
|
- [ ] Bot status toggle (enable/disable route)
|
|
- [ ] Contacts table with all filters
|
|
- [ ] Slide-out detail panel
|
|
- [ ] CSV export
|
|
|
|
### Phase 6 — Analytics (Day 3-4)
|
|
- [ ] Stat cards with sparklines
|
|
- [ ] Messages over time chart (Recharts)
|
|
- [ ] Conversations by bot bar chart
|
|
- [ ] Outcome distribution donut chart
|
|
- [ ] Bot leaderboard table
|
|
- [ ] Date range picker
|
|
|
|
### Phase 7 — Routing + Settings (Day 4)
|
|
- [ ] Phone number routing view with visual connections
|
|
- [ ] Route config modal (business hours, greeting, max concurrent)
|
|
- [ ] Settings page with credential cards
|
|
- [ ] Connection testing
|
|
- [ ] Webhook URL display with copy
|
|
|
|
### Phase 8 — Polish (Day 4-5)
|
|
- [ ] Loading states + skeletons
|
|
- [ ] Error handling + toast notifications
|
|
- [ ] Mobile responsive adjustments
|
|
- [ ] Auth gate (simple login)
|
|
- [ ] README with deploy instructions
|
|
|
|
---
|
|
|
|
## 9. EXTERNAL DEPENDENCIES
|
|
|
|
### npm packages:
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"next": "^14.2",
|
|
"react": "^18.3",
|
|
"twilio": "^5.0",
|
|
"better-sqlite3": "^11.0",
|
|
"recharts": "^2.12",
|
|
"lucide-react": "^0.400",
|
|
"@radix-ui/react-dialog": "^1.0",
|
|
"@radix-ui/react-dropdown-menu": "^2.0",
|
|
"@radix-ui/react-toggle": "^1.0",
|
|
"@radix-ui/react-slider": "^1.0",
|
|
"class-variance-authority": "^0.7",
|
|
"clsx": "^2.1",
|
|
"tailwind-merge": "^2.3",
|
|
"next-auth": "^4.24"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Environment Variables:
|
|
```env
|
|
# Twilio
|
|
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
|
# CloseBot
|
|
CLOSEBOT_API_KEY=cb_xxxxxxxxxxxxxxxx
|
|
|
|
# App
|
|
NEXTAUTH_SECRET=random-secret-here
|
|
NEXTAUTH_URL=https://your-domain.com
|
|
APP_URL=https://your-domain.com # Used to construct webhook URLs
|
|
|
|
# Database
|
|
DATABASE_PATH=./data/closebot-sms.db
|
|
```
|
|
|
|
---
|
|
|
|
## 10. WHAT MAKES THIS DIFFERENT
|
|
|
|
1. **No GHL required** — CloseBot's Webhook Source is the channel, Twilio is the pipe
|
|
2. **Multi-tenant ready** — one app, many Twilio numbers, many bots
|
|
3. **Human takeover** — click into any convo and type a manual reply
|
|
4. **Business hours built-in** — auto-reply after hours, resume bot in morning
|
|
5. **Full audit trail** — every message logged with direction, source, status
|
|
6. **Real-time everything** — SSE for live dashboard, no polling
|
|
7. **CloseBot metrics integrated** — booking rates, leaderboards, CSAT from their API
|
|
8. **$0.0079/SMS** — Twilio pricing, no GHL middleman markup
|
|
|
|
---
|
|
|
|
*Plan version: 1.0 | Last updated: 2026-02-06*
|