Nightly Build - 2026-02-04 (11 PM)

journal

Nightly Build - 2026-02-04 (11 PM)

What I Built Tonight

✅ HiddenBag Consensus Dashboard

Why: HiddenBag (Grade C) needs the consensus detection feature - this is what subscribers pay for. The "hot plays" where multiple cappers agree.

Files Created:

  1. src/app/consensus/page.tsx (~16KB)

    • Full consensus dashboard showing plays where 2+ cappers agree
    • Filters: by sport, by minimum capper count (2/3/4/5)
    • Sorts by: capper count (most confident first), then total units, then fewer opposing
    • Stats cards: Total plays, Hot plays (4+), Clean plays (0 opposing), Total capper picks
    • Each card shows: Team, spread, capper count, capper names, total units
    • Confidence badges using existing tier system
    • "Clean" badge for plays with no opposing cappers
    • Links to game detail pages for full breakdown
  2. src/app/api/consensus/route.ts (~6KB)

    • REST API endpoint for external use (alerts, bots, etc.)
    • Query params: ?sport=nba&minCappers=3
    • Returns JSON with:
      • plays[]: Array of consensus plays with game info, team, spread, cappers list
      • summary: Total plays, hot plays, clean plays counts
      • filters: Applied filters
      • timestamp: When data was fetched
  3. src/components/layout/Header.tsx (modified)

    • Added "🔥 Consensus" to main navigation (after Games)

How It Works

Data Flow:

hb_games (Supabase) → getGamesWithOdds()
hb_discord_messages → loadPicksSmart() → getPicksForGame()
                    ↓
             buildConsensusPlays()
                    ↓
        Filter by minCappers, Sort by confidence
                    ↓
              Render cards or JSON API

Consensus Logic:

  1. For each game, get home/away picks
  2. Group by unique cappers (de-dupe by capper name)
  3. If either side has 2+ unique cappers = consensus play
  4. Calculate total units, opposing count
  5. Sort: capperCount DESC → totalUnits DESC → opposingCappers ASC

Confidence Tiers:

  • 💎 Lock (4+ cappers)
  • 🔥 Strong (3 cappers)
  • 📍 Lean (2 cappers)

Build Results

  • ✅ TypeScript compiled (fixed ConfidenceTier type)
  • ✅ Build successful (15s compile + 690ms static gen)
  • ✅ Committed to master: 6698f18

What Matt Needs to Do

Nothing! This runs on the existing data pipeline. When Matt wakes up:

  1. Visit http://localhost:3001/consensus to see it locally
  2. Or deploy to Vercel for live: vercel --prod in hiddenbag-v2 folder

API Usage:

# Get all consensus plays
curl http://localhost:3001/api/consensus

# Get NBA plays with 3+ cappers
curl "http://localhost:3001/api/consensus?sport=basketball_nba&minCappers=3"

Why This Matters

This is the MONETIZATION FEATURE:

  • Free users: See games page with basic consensus bars
  • Paid users: Access to /consensus page with detailed breakdown
  • Future: Add auth gate to require subscription

The API enables:

  • Telegram alerts when hot plays (4+ cappers) appear
  • Discord bot integration
  • External dashboards

Next Steps (Future Nights)

  1. Auth Gate: Require subscription for /consensus page
  2. Auto-Alerts: Telegram notification when 4+ capper play detected
  3. Historical Tracking: Track consensus win/loss record
  4. Capper ROI: Add win/loss tracking per capper
  5. Weighted Consensus: Weight by capper ROI, not just count

Technical Notes

  • Used existing loadPicksSmart() which handles Vercel vs local
  • Reused getConfidenceTier() from confidence.ts
  • Page is server-side rendered (fresh data each load)
  • API uses standard Supabase client pattern

Files committed: 7 files, +1757 lines