# RateRight Growth Engine - Codebase Architecture Map

> Generated: 2026-01-28 | Version: 3.0 (Updated with 110+ features, Clawdbot, Notion, Dark Mode)

## Overview

RateRight Growth Engine is a comprehensive lead management and sales automation platform. It combines Express.js backend, React frontend, AI-powered sales assistance, and multi-channel communication (SMS/Voice) to help sales teams convert contractor leads.

**Tech Stack:**
- **Backend:** Express.js + Node.js
- **Frontend:** React + Vite + Tailwind CSS
- **Database:** Supabase (PostgreSQL)
- **AI:** OpenAI GPT-4o, Whisper
- **Voice:** Twilio Voice SDK (in-browser calling)
- **SMS:** Twilio Messaging
- **Live Transcription:** Deepgram Nova-2
- **Notifications:** Slack Webhooks
- **Deployment:** Railway (backend) + Vercel-ready (frontend)

---

## Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                         FRONTEND                                 │
│  React + Vite + Tailwind                                        │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌───────────┐ │
│  │Dashboard│ │CallList │ │ Leads   │ │LeadProf │ │  Inbox    │ │
│  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └─────┬─────┘ │
│       └───────────┴───────────┼───────────┴─────────────┘       │
│                               │                                  │
│  ┌────────────────────────────▼────────────────────────────┐    │
│  │                   API Client                             │    │
│  │  leadsApi │ smsApi │ callsApi │ aiApi │ voiceApi        │    │
│  └────────────────────────────┬────────────────────────────┘    │
└───────────────────────────────┼─────────────────────────────────┘
                                │ HTTPS
┌───────────────────────────────▼─────────────────────────────────┐
│                         BACKEND                                  │
│  Express.js + Node.js                                           │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                     ROUTES                                │   │
│  │  /health │ /leads │ /sms │ /calls │ /voice │ /ai │ /jobs │   │
│  └────────────────────────────┬─────────────────────────────┘   │
│                               │                                  │
│  ┌────────────────────────────▼────────────────────────────┐    │
│  │                    SERVICES                              │    │
│  │  twilio │ ai │ deepgram │ scoring │ slack │ templates   │    │
│  └────────────────────────────┬────────────────────────────┘    │
│                               │                                  │
│  ┌────────────────────────────▼────────────────────────────┐    │
│  │                      JOBS                                │    │
│  │  platformSync (15m) │ dailySummary (7am) │ scoreRecalc  │    │
│  └──────────────────────────────────────────────────────────┘   │
└───────────────────────────────┬─────────────────────────────────┘
                                │
        ┌───────────────────────┼───────────────────────┐
        │                       │                       │
        ▼                       ▼                       ▼
┌───────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Supabase    │     │     Twilio      │     │     OpenAI      │
│  PostgreSQL   │     │  SMS + Voice    │     │  GPT-4o/Whisper │
└───────────────┘     └─────────────────┘     └─────────────────┘
```

---

## Directory Structure

```
rateright-growth-deploy/
├── src/                          # Backend source
│   ├── index.js                  # Express entry point
│   ├── config/
│   │   └── database.js           # Supabase client
│   ├── routes/
│   │   ├── health.js             # GET /health, /health/ping
│   │   ├── leads.js              # CRUD /api/leads
│   │   ├── webhooks.js           # Twilio inbound webhooks
│   │   ├── sms.js                # SMS send/batch/templates
│   │   ├── calls.js              # Call logging
│   │   ├── callList.js           # Prioritized call list
│   │   ├── voice.js              # Twilio Voice SDK tokens
│   │   ├── ai.js                 # AI endpoints (25+ methods)
│   │   └── jobs.js               # Manual job triggers
│   ├── services/
│   │   ├── twilio.js             # SMS & Voice SDK
│   │   ├── ai.js                 # OpenAI integration
│   │   ├── deepgram.js           # Live transcription
│   │   ├── scoring.js            # Lead scoring algorithm
│   │   ├── slack.js              # Slack notifications
│   │   ├── templates.js          # SMS template rendering
│   │   └── learning.js           # Conversion pattern capture & feedback
│   ├── jobs/
│   │   ├── index.js              # Job scheduler
│   │   ├── platformSync.js       # RateRight API sync
│   │   └── dailySummary.js       # Daily metrics
│   └── utils/
│       ├── intent.js             # SMS intent classification
│       └── phone.js              # AU phone normalization
│
├── admin/                        # Frontend source
│   ├── src/
│   │   ├── App.jsx               # Router + layout
│   │   ├── main.jsx              # Entry point
│   │   ├── api/
│   │   │   └── client.js         # API client (all endpoints)
│   │   ├── context/
│   │   │   ├── AuthContext.jsx   # Supabase auth
│   │   │   └── CallContext.jsx   # In-app calling + auto-transcription
│   │   ├── pages/
│   │   │   ├── Dashboard.jsx     # Stats overview + AI insights
│   │   │   ├── CallList.jsx      # Daily call queue
│   │   │   ├── Activity.jsx      # Manager call reporting (NEW)
│   │   │   ├── Leads.jsx         # Lead database
│   │   │   ├── LeadProfile.jsx   # Lead detail + AI tools
│   │   │   ├── Inbox.jsx         # Inbound SMS
│   │   │   ├── Login.jsx         # Auth page
│   │   │   └── More.jsx          # Settings
│   │   ├── components/           # 22 UI components
│   │   │   ├── LeadCard.jsx
│   │   │   ├── ScoreBadge.jsx
│   │   │   ├── CallOutcomeSheet.jsx
│   │   │   ├── IntelBriefModal.jsx
│   │   │   ├── PostCallSummarySheet.jsx
│   │   │   ├── AIMessageWriter.jsx
│   │   │   ├── LiveCopilot.jsx
│   │   │   ├── TwilioCall.jsx
│   │   │   ├── VoiceAssistant.jsx
│   │   │   ├── VoiceRecorder.jsx
│   │   │   └── ... (more)
│   │   └── lib/
│   │       └── supabase.js       # Supabase client
│   └── package.json
│
├── public/                       # Pre-built admin UI
├── supabase/
│   ├── schema.sql                # Core tables
│   ├── ai-schema.sql             # AI tables
│   ├── learning-schema.sql       # Learning system tables
│   └── ideas-schema.sql          # Ideas/strategy capture
├── docs/
│   └── CODEBASE_MAP.md           # This file
├── BUILD-GUIDE.md                # Build documentation
├── package.json
└── railway.json                  # Railway deployment config
```

---

## Core Data Models

### Leads
```sql
leads (
  id UUID PRIMARY KEY,
  first_name, last_name, email, phone, company,
  source VARCHAR,          -- 'website', 'referral', 'import', 'platform'
  status VARCHAR,          -- 'new', 'engaged', 'converted', 'opted_out', 'archived'
  score INT (0-100),       -- Calculated by scoring service
  lead_type VARCHAR,       -- 'worker', 'business', 'agency'
  trade VARCHAR,           -- 'plumber', 'electrician', etc.
  assigned_to VARCHAR,
  last_contact_at TIMESTAMP,
  ai_conversion_probability FLOAT,
  ai_intel_brief JSONB,
  metadata JSONB,
  deleted_at TIMESTAMP     -- Soft delete
)
```

### Communications
```sql
communications (
  id UUID PRIMARY KEY,
  lead_id UUID REFERENCES leads,
  type VARCHAR,            -- 'sms_inbound', 'sms_outbound', 'call_outbound'
  direction VARCHAR,       -- 'inbound', 'outbound'
  phone VARCHAR,
  content TEXT,
  delivery_status VARCHAR,
  metadata JSONB {
    intent, confidence, outcome, duration_seconds, objections
  }
)
```

### Callbacks
```sql
callbacks (
  id UUID PRIMARY KEY,
  lead_id UUID REFERENCES leads,
  scheduled_at TIMESTAMP,
  reason TEXT,
  priority VARCHAR,        -- 'high', 'medium'
  status VARCHAR,          -- 'pending', 'completed', 'cancelled'
  source VARCHAR           -- 'sms_inbound', 'call_outbound', 'ai_recommendation'
)
```

### Lead Notes
```sql
lead_notes (
  id UUID PRIMARY KEY,
  lead_id UUID REFERENCES leads,
  content TEXT,
  created_by VARCHAR,      -- User email or 'copilot'
  created_at TIMESTAMP
)
```

### Conversion Patterns (Learning System)
```sql
conversion_patterns (
  id UUID PRIMARY KEY,
  lead_id UUID REFERENCES leads,
  lead_name, lead_company, lead_trade, lead_source,
  lead_score_at_conversion INT,
  days_to_convert INT,
  total_touchpoints INT,
  calls_made INT, sms_sent INT, sms_received INT,
  winning_channel VARCHAR,       -- 'call', 'sms', 'both'
  objections_raised JSONB,       -- [{objection, type, response_used, was_overcome}]
  objection_count INT,
  ai_suggestions_shown INT,
  ai_suggestions_helpful INT,
  winning_messages JSONB,        -- SMS that got positive responses
  copilot_suggestions_used JSONB,
  conversion_type VARCHAR,       -- 'manual', 'job_posted', etc.
  converted_by VARCHAR
)
```

### Objection Responses (Learning System)
```sql
objection_responses (
  id UUID PRIMARY KEY,
  objection_type VARCHAR,        -- 'price', 'timing', 'competition', 'trust'
  objection_text TEXT,
  response_text TEXT,
  times_shown INT,
  times_helpful INT,
  times_not_helpful INT,
  led_to_conversion INT,
  effectiveness_score DECIMAL    -- 0 to 1, auto-calculated
)
```

### Suggestion Feedback (Learning System)
```sql
suggestion_feedback (
  id UUID PRIMARY KEY,
  copilot_session_id UUID,
  lead_id UUID,
  objection_detected TEXT,
  suggestion_response TEXT,
  was_helpful BOOLEAN
)
```

---

## API Reference

### Health
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/health` | Full system status |
| GET | `/health/ping` | Simple ping for load balancer |

### Leads
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/leads` | List with filters (status, score, search) |
| GET | `/api/leads/:id` | Get with comms, notes, callbacks |
| POST | `/api/leads` | Create new lead |
| PATCH | `/api/leads/:id` | Update lead |
| DELETE | `/api/leads/:id` | Soft delete |
| POST | `/api/leads/import-sheet` | Bulk import CSV |

### SMS
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/sms/templates` | List templates |
| POST | `/api/sms/send` | Send single SMS |
| POST | `/api/sms/batch` | Send to multiple leads |
| POST | `/api/sms/preview` | Preview template |

### Calls
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/calls/outcomes` | Valid outcome options |
| POST | `/api/calls/log` | Log call result |

### Voice (Twilio SDK)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/voice/token` | Generate browser calling token |
| POST | `/api/voice/twiml` | TwiML for outbound call |
| POST | `/api/voice/inbound` | Handle incoming calls (PUBLIC) |
| POST | `/api/voice/inbound-status` | Missed call handling + voicemail (PUBLIC) |
| POST | `/api/voice/voicemail` | Voicemail transcription webhook (PUBLIC) |
| POST | `/api/voice/voicemail-complete` | Save voicemail recording (PUBLIC) |
| POST | `/api/voice/call-status` | Call status webhook |
| GET | `/api/voice/lookup-caller` | Look up lead by phone for caller ID |
| GET | `/api/voice/status` | Voice config status |

### AI
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/ai/intel-brief/:leadId` | Pre-call intelligence |
| POST | `/api/ai/post-call-summary` | Analyze call transcript |
| POST | `/api/ai/draft-message` | AI SMS draft |
| POST | `/api/ai/transcribe` | Audio to text (Whisper) |
| POST | `/api/ai/voice-command` | Parse voice command |
| POST | `/api/ai/objection-response` | Handle objection |
| GET | `/api/ai/conversion-probability/:leadId` | Conversion % |
| POST | `/api/ai/weekly-insights` | Pattern analysis |
| POST | `/api/ai/cleanup-notes` | Format rough notes |
| GET | `/api/ai/deepgram-credentials` | Live transcription creds |
| POST | `/api/ai/copilot-session` | Save call session |
| POST | `/api/ai/suggestion-feedback` | Thumbs up/down on suggestion |
| GET | `/api/ai/effective-responses/:type` | Top responses for objection type |
| GET | `/api/ai/similar-wins/:leadId` | Similar conversion patterns |

### Webhooks
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/webhooks/twilio/inbound` | Receive SMS |
| POST | `/api/webhooks/twilio/status` | Delivery status |

### Jobs
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/jobs` | List available jobs |
| POST | `/api/jobs/:name` | Trigger job manually |

---

## Data Flows

### Inbound SMS Flow
```
Twilio SMS → /api/webhooks/twilio/inbound
    │
    ├─→ Normalize phone number
    ├─→ Lookup/create lead
    ├─→ Classify intent (positive/negative/question)
    ├─→ Log communication
    ├─→ Update lead status
    ├─→ Create callback (if positive/question)
    ├─→ Send auto-reply
    └─→ Post Slack alert
```

### In-App Calling Flow (with Auto-Transcription)
```
User clicks Call → /api/voice/token (get JWT)
    │
    ├─→ Browser connects via Twilio Voice SDK
    ├─→ /api/voice/twiml returns dial instructions
    ├─→ Call connects to lead
    │     └─→ CallContext auto-starts transcription (Deepgram/Web Speech)
    │     └─→ "Recording & Transcribing" indicator shown
    ├─→ LiveCopilot available for real-time AI help
    ├─→ Call ends
    │     └─→ Transcription stops
    │     └─→ Auto-generate AI summary from transcript
    ├─→ CallOutcomeSheet opens (pre-populated)
    │     ├─→ Notes: auto-filled with AI summary
    │     ├─→ Outcome: auto-suggested by AI
    │     ├─→ Score adjustment: shown from AI
    │     └─→ User confirms and saves
    └─→ Transcript + summary stored in communications metadata
```

### Inbound Call Flow (with Scoring)
```
Lead calls your Twilio number → /api/voice/inbound
    │
    ├─→ Normalize phone number
    ├─→ Lookup lead in database
    │     └─→ If found: +20 points to score
    │     └─→ Track inbound_call_count++
    │     └─→ Flag is_high_intent if 3+ calls
    ├─→ Send Slack alert (with HIGH INTENT if applicable)
    ├─→ Ring browser client (IncomingCallHandler)
    │     └─→ Hot leads: 60s ring time
    │     └─→ Regular: 30s ring time
    │
    ├─→ If answered: Call proceeds normally
    │
    └─→ If not answered → /api/voice/inbound-status
          ├─→ Create callback (URGENT for hot leads)
          ├─→ Hot leads: auto-send SMS "Sorry I missed you"
          ├─→ Send Slack missed call alert
          └─→ Voicemail prompt
                └─→ Recording saved immediately
                └─→ Transcription added async
```

### AI Intel Brief Flow
```
User clicks Intel Brief → /api/ai/intel-brief/:leadId
    │
    ├─→ Fetch lead data
    ├─→ Fetch recent communications
    ├─→ Find similar converted leads
    ├─→ Call GPT-4o with context
    └─→ Return: summary, objections, talking points, opening line
```

### Lead Scoring Flow
```
Activity occurs (SMS reply, call, platform action)
    │
    ├─→ Trigger score recalculation
    ├─→ Apply scoring rules:
    │     • SMS positive: +40
    │     • SMS question: +20
    │     • SMS negative: -100
    │     • Call interested: +30
    │     • Call not interested: -50
    │     • Job posted: +50
    │     • INBOUND CALL: +20 (each time they call you!)
    │     • Decay: -2/day after 7 days
    └─→ Update lead.score (bound 0-100)
```

### Learning System Flow
```
Lead status → 'converted' (via PATCH /api/leads/:id)
    │
    ├─→ captureConversionPattern() auto-triggered
    │     • Pull lead data, communications, copilot sessions
    │     • Calculate days_to_convert, touchpoints
    │     • Extract objections raised & responses used
    │     • Identify winning messages & channel
    ├─→ Store in conversion_patterns table
    └─→ Update objection_responses effectiveness scores

User clicks thumbs up/down on AI suggestion
    │
    ├─→ POST /api/ai/suggestion-feedback
    ├─→ Store in suggestion_feedback table
    └─→ Update objection_responses effectiveness score
```

---

## Score Tiers & Prioritization

| Tier | Score Range | Priority |
|------|-------------|----------|
| Hot | 70-100 | Immediate follow-up |
| Warm | 50-69 | Secondary priority |
| Cool | 20-49 | Standard follow-up |
| Cold | 0-19 | Minimal engagement |
| Dead | Below 0 | Opted out / wrong number |

**Call List Priority Order:**
1. Inbound SMS replies (positive/question)
2. Hot leads (70+)
3. Scheduled callbacks due today
4. Recent platform activity (7 days)
5. Warm leads (50-69)
6. Cool leads (20-49)

---

## Key Services

### Twilio Service (`src/services/twilio.js`)
- `sendSMS(to, body)` - Send single SMS
- `sendBatchSMS(messages)` - Batch send with 100ms delay
- `generateVoiceToken(identity)` - JWT for browser calling
- `isConfigured()` - Check SMS setup
- `isVoiceConfigured()` - Check Voice setup

### AI Service (`src/services/ai.js`)
- `generateIntelBrief(lead, comms, similarWins)` - Pre-call prep
- `generatePostCallSummary(lead, transcript, duration)` - Call analysis
- `draftMessage(lead, prompt, comms)` - SMS draft
- `transcribeAudio(buffer, filename)` - Whisper transcription
- `parseVoiceCommand(transcript)` - Voice intent parsing
- `getObjectionResponse(objection, lead)` - Objection handling
- `calculateConversionProbability(lead, comms, factors)` - Conversion %
- `generateWeeklyInsights(metrics, conversions, comms)` - Pattern analysis

### Scoring Service (`src/services/scoring.js`)
- `calculateLeadScore(leadId)` - Score with breakdown
- `updateLeadScore(leadId)` - Save to DB
- `recalculateAllScores()` - Batch recalc
- `getScoreTier(score)` - Return tier name

### Learning Service (`src/services/learning.js`)
- `captureConversionPattern(leadId, type, convertedBy)` - Auto-captures when lead converts
- `recordSuggestionFeedback(data)` - Thumbs up/down on AI suggestions
- `getEffectiveResponses(objectionType, trade)` - Top performing responses
- `getSimilarWins(lead)` - Find similar conversion patterns

---

## Frontend Components

### Pages
| Page | Path | Purpose |
|------|------|---------|
| Dashboard | `/` | Stats overview + AI insights |
| CallList | `/call-list` | Daily prioritized queue |
| Leads | `/leads` | Lead database + filters |
| LeadProfile | `/leads/:id` | Detail view + all AI tools + High Intent alerts |
| Inbox | `/inbox` | Inbound SMS + Voicemails (with playback) |

### Key Components
| Component | Purpose |
|-----------|---------|
| `TwilioCall` | In-browser calling UI |
| `IncomingCallHandler` | Fullscreen incoming call UI with ringtone |
| `LiveCopilot` | Real-time call assistance |
| `IntelBriefModal` | Pre-call AI brief |
| `PostCallSummarySheet` | Post-call AI analysis |
| `AIMessageWriter` | AI-powered SMS drafting |
| `CallOutcomeSheet` | Log call result |
| `VoiceAssistant` | Voice command floating button |
| `VoiceRecorder` | Audio capture for notes |
| `PredictiveScoreBadge` | Conversion probability |

### Contexts
| Context | Purpose |
|---------|---------|
| `AuthContext` | Supabase auth + session |
| `CallContext` | Global call state + auto-transcription + auto-summary |
| `RealtimeContext` | Supabase realtime subscriptions + notification sounds |

---

## Environment Variables

### Backend (Required)
```env
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
TWILIO_ACCOUNT_SID=AC...
TWILIO_AUTH_TOKEN=xxx
TWILIO_PHONE_NUMBER=+614xxxxxxxx
OPENAI_API_KEY=sk-...
```

### Backend (Optional)
```env
TWILIO_API_KEY_SID=SK...        # For Voice SDK
TWILIO_API_KEY_SECRET=xxx       # For Voice SDK
TWILIO_TWIML_APP_SID=AP...      # For Voice SDK
DEEPGRAM_API_KEY=xxx            # For live transcription
SLACK_WEBHOOK_URL=https://...   # For notifications
RATERIGHT_API_URL=https://...   # Platform sync
RATERIGHT_ADMIN_API_KEY=xxx     # Platform sync
```

### Frontend
```env
VITE_API_URL=https://rateright-growth-production.up.railway.app
VITE_SUPABASE_URL=https://xxx.supabase.co
VITE_SUPABASE_ANON_KEY=eyJ...
```

---

## Scheduled Jobs

| Job | Schedule | Description |
|-----|----------|-------------|
| Platform Sync | Every 15 min | Sync activity from RateRight API |
| Score Recalc | Every hour | Recalculate all lead scores |
| Daily Summary | 7am AEST | Send Slack metrics report |

---

## Key Files Quick Reference

| File | Lines | Purpose |
|------|-------|---------|
| `src/index.js` | ~80 | Express server entry |
| `src/routes/ai.js` | ~850 | All AI endpoints |
| `src/routes/leads.js` | ~350 | Lead CRUD + conversion hook |
| `src/services/ai.js` | ~400 | OpenAI integration |
| `src/services/learning.js` | ~470 | Learning system |
| `src/services/scoring.js` | ~150 | Scoring algorithm |
| `admin/src/pages/LeadProfile.jsx` | ~440 | Lead detail page |
| `admin/src/pages/CallList.jsx` | ~300 | Call queue page |
| `admin/src/components/LiveCopilot.jsx` | ~550 | Real-time AI + feedback |
| `admin/src/api/client.js` | ~110 | API client |

---

## Known Limitations

1. **No RLS** - Row Level Security not enabled (single-tenant)
2. ~~**No Real-time** - WebSocket updates not implemented~~ ✅ FIXED - RealtimeContext with Supabase subscriptions
3. ~~**Recording Transcription** - Manual, not automatic~~ ✅ FIXED - Auto-transcription now enabled
4. **Sequence Automation** - Schema exists, not executed
5. **No Request Validation** - Basic validation only
6. **No Rate Limiting** - Middleware not implemented
7. **Weekly Report** - Exists but passive (user must trigger)

---

## Deployment

**Railway (Backend):**
- Builder: NIXPACKS
- Start: `npm start`
- Health check: `/health/ping`
- Auto-restart on failure

**Frontend:**
- Pre-built in `/public` folder
- Served by Express static middleware
- Alternative: Deploy `admin/` to Vercel/Netlify

---

## Battleground / Gamification System

The Battleground is a competitive gamification layer built on top of the CRM.

### Data Models
```sql
-- Core XP tracking
user_xp (
  user_id UUID PRIMARY KEY,
  display_name VARCHAR,
  total_xp INT,
  level INT,
  current_streak INT,
  streak_tier VARCHAR,       -- 'bronze', 'silver', 'gold', 'diamond'
  current_badges JSONB,
  status VARCHAR             -- 'grinding', 'on-fire', etc.
)

-- XP history for leaderboard periods
xp_history (
  id UUID PRIMARY KEY,
  user_id UUID,
  amount INT,
  reason VARCHAR,
  created_at TIMESTAMP
)

-- Daily/team challenges
daily_challenges (
  id UUID PRIMARY KEY,
  user_id UUID,
  challenge_type VARCHAR,
  target INT,
  progress INT,
  completed BOOLEAN,
  date DATE
)

-- Team activity feed
team_pulse (
  id UUID PRIMARY KEY,
  event_type VARCHAR,
  user_id UUID,
  user_name VARCHAR,
  title TEXT,
  subtitle TEXT,
  emoji VARCHAR,
  created_at TIMESTAMP
)

-- All-time records
hall_of_fame (
  record_type VARCHAR PRIMARY KEY,
  user_id UUID,
  user_name VARCHAR,
  value INT,
  achieved_at TIMESTAMP
)

-- Position tracking for "overtake" alerts
leaderboard_snapshots (
  user_id UUID,
  period VARCHAR,
  snapshot_date DATE,
  position INT,
  PRIMARY KEY (user_id, period, snapshot_date)
)
```

### Backend Files
| File | Purpose |
|------|---------|
| `src/routes/battleground.js` | API endpoints: leaderboard, challenges, pulse, badges, streaks |
| `src/routes/xp.js` | XP award/query endpoints |
| `src/services/leaderboardService.js` | Leaderboard logic, hall of fame, team pulse |
| `src/services/challengesService.js` | Daily challenge generation and progress |
| `src/services/badgesService.js` | Weekly badge awards |
| `src/services/xpService.js` | XP award logic |

### Frontend Files
| File | Purpose |
|------|---------|
| `admin/src/pages/Battleground.jsx` | Main battleground page |
| `admin/src/components/gamification/LiveLeaderboard.jsx` | Real-time leaderboard |
| `admin/src/components/gamification/DailyChallenges.jsx` | Challenge cards |
| `admin/src/components/gamification/StreakWars.jsx` | Streak tiers |
| `admin/src/components/gamification/HallOfFame.jsx` | All-time records |
| `admin/src/components/gamification/TeamPulseFeed.jsx` | Activity feed |
| `admin/src/context/XPContext.jsx` | XP celebrations |
| `admin/src/api/client.js` | `battlegroundApi`, `xpApi` exports |

### Known Issues (2026-01-18)
**CRITICAL: User ID mismatch** - See `docs/battleground-investigation-report.md`

Routes using wrong pattern `req.headers['x-user-id']` instead of `req.user?.id`:
- xp.js (lines 53, 120, 243)
- achievements.js (lines 247, 301)
- aiAlerts.js (lines 27, 76, 119, 143, 166, 189)
- analytics.js (line 15)
- coaching.js (lines 59, 115, 205, 277)
- sms.js (line 355)
- dashboard.js (line 1642)

All XP/gamification data is being stored under `'default-user'` instead of real user IDs.

---

*Last updated: 2026-01-18 (Battleground investigation, High Intent SMS fixes)*
