Files
botfights/.claude/plans/concurrent-meandering-muffin.md
T
DorianandClaude Opus 4.6 610e799605 feat: SSE live fight spectating with spectator count
Enable real-time fight spectating for all live fights (not just human
fights). Multiple spectators can watch simultaneously via SSE. Spectator
count is tracked per-fight and broadcast with every SSE event.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:46:39 +00:00

23 KiB
Raw Blame History

Botfights: 6-Month Development Plan (MarchSeptember 2026)

Current State (March 8, 2026)

Botfights is a competitive AI fighting game (Vue 3 + Kaplay + Hono/SQLite) where bots battle through challenge rounds with pixel art sprites, synthesized audio, and choreographed fight animations. The core is feature-complete:

Category Count Status
Archetypes 101 (100 + THE CREATOR) Done
Choreographies 352+ (300 base + 40 tier-gated + 12 creator) Done
Challenge Types 16 Done
Challenge Prompts 800 (551 multiple-choice, 249 creative) Done
Mock Bots 100 (tiers 06) Done
Arenas 25 with modifiers Done
Voice Profiles 60+ Done
Music Tracks 10 procedural synth Done
Sound Effects 30+ Done
Pages 20 Done
Nostr Auth NIP-04/44/19 Done
Payments NWC + Lightning Address + Cashu Done
PWA Manifest + SW + offline assets Done
Docker Multi-stage, 42MB prod image Done
TUI Fight Loop Live round-by-round Done
Production Hardening Security headers, SSRF, rate limiting, graceful shutdown Done

FightScene.ts is 11,313 lines. The codebase works end-to-end but hasn't been battle-tested with real users at scale.


Month 1: Social Layer & Real-Money Launch (March 9 April 5)

Goal: Make botfights a place people want to hang out and bet sats.

Week 1: Spectator Experience

1.1 Live Fight Spectating via SSE

Files: server/src/routes/fights.ts, frontend/src/pages/FightPage.vue

  • SSE endpoint streams round results, HP changes, challenge reveals in real-time
  • Multiple spectators can watch a live fight simultaneously
  • Auto-redirect from fight card to live view when fight starts
  • Spectator count badge on active fights

1.2 Fight Feed / Activity Stream

New file: frontend/src/pages/FeedPage.vue

  • Reverse-chronological feed of recent fights: winner, KO/decision, Elo changes
  • Filter by tier, arena, bot name
  • Click any fight to watch replay
  • Replace or augment current HomePage with this

1.3 Reactions / Crowd Noise

Files: frontend/src/components/FightViewer.vue, server/src/routes/fights.ts

  • Spectators can send emoji reactions during live fights (fist, fire, skull, 100, clown)
  • Reactions appear as floating particles over the fight
  • Server aggregates reactions, broadcasts via SSE
  • Crowd SFX intensity scales with reaction count

Week 2: Betting System UI

2.1 Bet Placement UI

Files: frontend/src/components/BetPanel.vue, frontend/src/pages/FightCardPage.vue

  • Pre-fight bet panel: pick winner, set amount (21/100/500/1000 sats)
  • Cashu token deposit flow (paste token or scan QR)
  • NWC direct-pay option for connected wallets
  • Odds display based on Elo difference
  • Bet confirmation with payout preview

2.2 Bet Settlement & Payout

Files: server/src/engine/betting.ts, server/src/engine/payments.ts

  • Atomic settlement on fight completion
  • Winner payout minus 5% house cut (goes to fight pot for ranked matches)
  • Cashu token minting for winnings OR Lightning payout
  • Refund on cancelled/errored fights

2.3 Betting History

Files: frontend/src/pages/BotProfilePage.vue, new frontend/src/components/BetHistory.vue

  • Personal bet history on profile page
  • P&L tracking (total wagered, total won, net)
  • "Hot streak" and "cold streak" indicators

Week 3: Nostr Social Integration

3.1 Fight Results to Nostr

New file: server/src/engine/nostr-publish.ts

  • Post NIP-01 kind:1 notes for notable fights (KOs, perfects, upsets, tier changes)
  • Include fight replay link, bot names, Elo changes
  • Configurable relay list via env var
  • Only publish if BOTFIGHTS_NOSTR_NSEC is set

3.2 Nostr Profile Enrichment

Files: frontend/src/composables/useNostr.ts, frontend/src/pages/BotProfilePage.vue

  • Fetch NIP-05, display name, banner from Nostr relays
  • Show Nostr profile picture alongside bot sprite
  • Link to user's Nostr profile (njump.me or similar)

3.3 Zap Integration

Files: frontend/src/components/FightViewer.vue, server/src/routes/payments.ts

  • "Zap the winner" button after fight ends
  • NWC zap flow: create invoice, user approves, confirm
  • Zap receipts displayed on bot profile

Week 4: Ranked Season System

4.1 Season Framework

New file: server/src/engine/seasons.ts

  • Season = 2 weeks, auto-rotates
  • Season Elo resets to soft floor (blend of final Elo + 1200 baseline)
  • Season leaderboard separate from all-time
  • Season rewards: title badges, exclusive arena unlocks

4.2 Season Leaderboard UI

Files: frontend/src/pages/LeaderboardPage.vue

  • Toggle between "This Season" and "All Time"
  • Season countdown timer
  • Top 3 highlighted with crown/medal sprites
  • Season history archive

4.3 Ranked Queue Improvements

Files: server/src/engine/ranked-queue.ts, frontend/src/pages/JoinBoutPage.vue

  • Elo-bracket matchmaking (±200 Elo, widens over time)
  • Ranked queue status indicator (how many waiting)
  • Estimated wait time
  • Ranked-only challenges (harder prompts, no multiple choice)

Month 2: Tournaments, Human Play & Content Expansion (April 6 May 3)

Goal: Structured competition and enough content that nothing feels repetitive.

Week 5: Tournament System

5.1 Tournament Engine

New files: server/src/engine/tournaments.ts, server/src/db/schema.ts (new tables)

  • Single-elimination brackets (8, 16, 32 bots)
  • Round-robin group stage option
  • Entry fee (configurable sats amount) → prize pool
  • Auto-advance winners, schedule next round
  • DB tables: tournaments, tournament_entries, tournament_matches

5.2 Tournament UI

New files: frontend/src/pages/TournamentPage.vue, frontend/src/pages/TournamentListPage.vue

  • Visual bracket display (SVG or canvas)
  • Live bracket updates as fights complete
  • Tournament lobby: registered bots, countdown to start
  • Results page with champion highlight

5.3 Scheduled Tournaments

Files: server/src/engine/fight-loop.ts, server/src/engine/tournaments.ts

  • Daily automated tournaments (e.g., 8pm UTC)
  • "The Halvening" weekly 32-bot major tournament
  • Special themed tournaments (code-golf only, roast-battle only)
  • Cron-based scheduling via fight loop

Week 6: Human vs Bot Improvements

6.1 Human Fight Polish

Files: frontend/src/pages/HumanFightPage.vue, server/src/engine/human-responses.ts

  • Fix the TODO in human-responses.ts (currently pass # TODO: implement)
  • Mobile-optimized input (large buttons for multiple choice, big text area for creative)
  • Countdown timer with visual urgency (color shift, shake)
  • Immediate feedback after answering (correct/wrong animation)

6.2 Practice Mode

New file: frontend/src/pages/PracticePage.vue

  • Fight against mock bots without Elo impact
  • Choose difficulty tier
  • Post-fight breakdown: which rounds you won/lost and why
  • Suggested improvements

6.3 Human vs Human

Files: server/src/engine/orchestrator.ts, server/src/routes/queue.ts

  • Real-time matchmaking for two human players
  • Both answer same challenge simultaneously
  • WebSocket or SSE for synchronization
  • Elo-rated human ladder separate from bot ladder

Week 7: Content Scaling

7.1 Challenge Prompts → 2,000

Files: server/src/engine/challenges.ts

  • 75 more prompts per existing 16 types = 1,200 new prompts
  • Focus on Bitcoin/cypherpunk themed prompts:
    • "What year was the Bitcoin whitepaper published?"
    • "Explain proof-of-work to a medieval blacksmith"
    • "Roast someone who thinks Ethereum is decentralized"
    • "Write a haiku about the mempool"
  • All factual types get multiple-choice options
  • Difficulty tiers: easy (tier 02 fights), medium (34), hard (56)

7.2 Music Tracks → 20

Files: frontend/src/game/sounds.ts

  • 10 new procedural tracks:
    • 2x Drum & Bass (170175 BPM)
    • 2x Lo-fi Hip Hop (90100 BPM)
    • 2x Ska Punk (200220 BPM)
    • 2x Boss Fight (140160 BPM, heavy)
    • 2x Chiptune (180200 BPM)
  • Intensity-grouped: low (lo-fi, chiptune), mid (ska, D&B), high (boss fight)

7.3 Arenas → 40

Files: server/src/engine/arenas.ts, frontend/src/game/FightScene.ts

  • 15 new arenas:
    • bitcoin_mine (hash_power modifier)
    • lightning_node (speed_3x)
    • satoshis_garage (legacy_code)
    • mempool (chaos_mode)
    • silk_road_ruins (trap_heavy)
    • block_height_tower (accuracy_buff)
    • hodl_cave (endurance_2x)
    • whale_pool (high_stakes)
    • node_farm (efficiency_buff)
    • genesis_block (all_types)
    • pizza_day_parlor (food_2x)
    • difficulty_adjustment (adaptive)
    • 51_percent_arena (chaos_mode)
    • timechain_temple (speed_2x)
    • nostr_relay_room (crowd_favorite)
  • Each with unique theme colors and background elements

Week 8: Choreography & Animation Polish

8.1 Choreographies → 500

Files: frontend/src/game/FightScene.ts

  • 148 new choreographies across categories:
    • 30 Bitcoin-themed (lightning_bolt, hash_smash, block_drop, mempool_flood, difficulty_bomb, fee_spike, utxo_scatter, node_sync, relay_bounce, channel_force_close, etc.)
    • 25 more food moves
    • 25 more energy/beam moves
    • 20 more silly/absurd moves
    • 20 more weapon moves
    • 15 more vehicle moves
    • 13 more animal moves
  • Wire into CHALLENGE_THEMED with balanced distribution

8.2 Entrance Animations

Files: frontend/src/game/FightScene.ts

  • 10 new tier-gated entrances:
    • Tier 01: simple walk-in
    • Tier 2: slide in with dust
    • Tier 3: drop from above with impact shake
    • Tier 4: teleport with lightning flash
    • Tier 5: dramatic slow-mo entrance with camera zoom
    • Tier 6: custom per-bot entrance (THE CREATOR golden portal already done)

8.3 Victory Celebrations

Files: frontend/src/game/FightScene.ts

  • Post-fight victory animations tied to finish type:
    • KO: winner flexes, camera flash effect
    • Perfect: winner does victory lap, confetti rain
    • Decision: both bow, crowd cheers
    • Upset: dramatic zoom on winner, shocked crowd SFX

Month 3: Scale, Polish & Launch (May 4 May 31)

Goal: Production-ready for real users, real sats, real competition.

Week 9: FightScene.ts Decomposition

9.1 Split the Monolith

FightScene.ts at 11,313 lines is the single biggest maintenance risk. Split into focused modules:

frontend/src/game/fight/
  index.ts              -- createFightScene() orchestrator
  types.ts              -- FightContext, shared interfaces
  constants.ts          -- arena themes, sprite anims, positions
  particles.ts          -- all particle spawn functions
  projectiles.ts        -- projectile spawning and physics
  effects.ts            -- screen effects (glitch, scanline, VHS, etc.)
  grotesque.ts          -- close-up detail system
  arena.ts              -- arena background rendering
  entrances.ts          -- bot entrance animations
  morphs.ts             -- morph system (elemental, mech, beast, omni)
  choreography/
    index.ts            -- choreographyMap, pickChoreography
    registry.ts         -- CHALLENGE_THEMED, critMoves
    basic.ts            -- punches, kicks, slams
    ranged.ts           -- projectiles, guns, beams
    heavy.ts            -- ground pounds, body slams
    weapons.ts          -- swords, hammers, etc.
    food.ts             -- food-themed moves
    silly.ts            -- absurd/comedy moves
    bitcoin.ts          -- Bitcoin-themed moves
    creator.ts          -- THE CREATOR exclusive moves
    ultimates.ts        -- tier-gated ultimate moves
  finishers.ts          -- KO styles, perfect finish
  round.ts              -- playRound, playTaunt, playDodge
  camera.ts             -- camera shake, zoom, pan
  hud.ts                -- HP bars, round counter, timer
  • Zero behavior changes — pure refactor
  • Each module receives FightContext object
  • Test: replay 50 fights, verify identical behavior

Week 10: Performance & Mobile

10.1 Performance Optimization

  • Profile FightScene with Chrome DevTools
  • Reduce particle count on mobile (detect via navigator.maxTouchPoints)
  • Lazy-load Kokoro TTS model (2.2MB) — don't block initial render
  • Sprite sheet atlas: batch all archetypes into single texture
  • RequestAnimationFrame budget monitoring — drop effects if frame time > 16ms

10.2 Mobile UX Polish

Files: Various frontend components

  • Touch-friendly bet panel (large tap targets, swipe gestures)
  • Responsive fight viewer (portrait mode layout)
  • Bottom navigation bar for mobile
  • Haptic feedback on hits (Vibration API)
  • Reduced motion mode (prefers-reduced-motion)

10.3 Offline / Weak Connection

  • Queue position preserved on reconnect (SSE retry)
  • Optimistic UI for bet placement
  • Replay cache: save last 10 watched fights for offline replay
  • Connection status indicator

Week 11: Admin, Analytics & Bot Developer Experience

11.1 Admin Dashboard

New files: frontend/src/pages/AdminPage.vue, server/src/routes/admin.ts

  • Protected by THE CREATOR pubkey (only admin)
  • Live stats: active fights, queue depth, bets in escrow, total sats moved
  • Bot management: deactivate, reset Elo, ban
  • Challenge management: add/remove prompts, preview scoring
  • Fight log viewer with full round details
  • System health: DB size, memory, uptime

11.2 Privacy-Respecting Analytics

New file: server/src/engine/analytics.ts

  • No PII, no cookies, no third-party scripts
  • Aggregate counts only: fights/day, unique bots/day, sats wagered/day
  • Stored in SQLite, queryable from admin dashboard
  • Public stats endpoint for transparency: GET /api/stats/public

11.3 Bot Developer Docs

Files: frontend/src/pages/DocsPage.vue

  • Interactive API explorer (try endpoints from the browser)
  • Webhook payload examples for all 16 challenge types
  • Response format with scoring breakdown
  • "Build your first bot" tutorial (curl, Python, Node examples)
  • Webhook testing tool (send test challenge, see response + score)

Week 12: Launch Prep & Stress Testing

12.1 Load Testing

  • Simulate 100 concurrent spectators on single fight
  • Simulate 20 concurrent fights
  • Simulate 50 concurrent bet placements
  • SQLite WAL mode verification under write contention
  • Memory profiling under sustained fight-loop operation (24hr soak test)

12.2 Backup & Recovery

New file: server/src/engine/backup.ts

  • Automated SQLite backup to file (daily rotation, keep 7)
  • Export fight history as JSON (for Nostr archival)
  • Elo snapshot before season reset (rollback safety)

12.3 Launch Checklist

  • All 16 challenge types tested end-to-end with real webhook
  • NWC payment flow tested with real sats (testnet then mainnet)
  • Cashu token deposit + withdrawal tested
  • Betting flow: place bet → watch fight → receive payout
  • Tournament: create → fill → run → settle prizes
  • Human fight: join queue → answer challenges → see result
  • Mobile: full flow on iOS Safari + Android Chrome
  • PWA: install → offline → reconnect → resume
  • TUI fight loop: 24hr soak test without crash
  • Docker: fresh build → deploy → health check → seed → fight
  • Nostr: fight results published to relay, zaps working
  • Security: rate limiting, SSRF, body limits, error hiding verified
  • THE CREATOR: all exclusive features working (entrance, morphs, cameo, moves)
  • Bundle size < 300KB gzipped (run npx vite-bundle-visualizer)
  • Memory: 50-fight replay stays flat (Chrome DevTools heap snapshot)
  • Server: 24hr fight-loop RSS < 250MB
  • Mobile: fight loads in < 2s on throttled 4G
  • SQLite: indexes verified, WAL mode enabled, p95 query < 50ms

Performance & Footprint (Continuous Thread)

Performance is not a one-week task — it's a discipline that runs across all 3 months. Every feature addition must respect these budgets.

Budgets

Metric Target Current Estimate
Initial JS bundle < 300KB gzipped Audit needed
Kokoro TTS model Lazy-load, < 2.2MB 2.2MB (loaded eagerly)
Sprite sheet per bot < 15KB PNG ~8KB
Fight replay memory < 80MB peak Unknown (profile needed)
Server memory (idle) < 100MB RSS ~60MB
Server memory (fight-loop 24hr) < 250MB RSS Unknown
Docker image < 50MB 42MB
SQLite DB after 10K fights < 200MB ~5MB (100 fights)
Time to first fight frame < 2s on 4G Unknown
SSE reconnect < 1s Unknown

Month 1 Performance Tasks

P1.1 Bundle Audit & Tree-Shaking

  • Run npx vite-bundle-visualizer to identify bloat
  • Verify Kaplay tree-shakes unused modules
  • Verify nostr-tools only imports what's needed (not full bundle)
  • Code-split routes: lazy-load all pages except HomePage
  • Target: identify top 3 bundle offenders and fix

P1.2 Kokoro TTS Lazy Loading

Files: frontend/src/game/sounds.ts

  • Don't load the 2.2MB Kokoro model on page load
  • Load on first fight start (with loading indicator)
  • Cache in service worker after first load
  • Fallback to Web Speech API while loading

P1.3 Sprite Atlas

Files: frontend/src/game/sprites/

  • Currently generates sprite sheets per-bot at fight time
  • Pre-generate common archetypes into a shared atlas texture
  • Single GPU texture upload instead of per-bot
  • Reduces fight init time and GPU memory

P1.4 SSE Connection Pooling

Files: server/src/routes/fights.ts

  • Ensure SSE connections are properly cleaned up on client disconnect
  • Add connection limit per IP (max 5 concurrent SSE streams)
  • Heartbeat every 15s to detect dead connections
  • Memory: track active SSE count in admin stats

Month 2 Performance Tasks

P2.1 Fight Replay Memory Profiling

  • Profile memory during 10-fight replay session
  • Identify particle/sprite leaks (Kaplay objects not destroyed)
  • Add fight.destroy() cleanup that nulls all references
  • Test: play 50 fights consecutively, memory should stay flat

P2.2 Choreography Performance Tiers

Files: frontend/src/game/FightScene.ts

  • Tag each choreography with a particleCount estimate
  • On low-end devices (detect via navigator.hardwareConcurrency < 4):
    • Reduce particle counts by 60%
    • Skip grotesque close-ups
    • Use simpler camera movements
    • Disable background arena animations
  • Toggle in settings: "Performance mode"

P2.3 SQLite Optimization

Files: server/src/db/index.ts

  • Enable WAL mode: PRAGMA journal_mode=WAL
  • Set PRAGMA synchronous=NORMAL (safe with WAL)
  • Add indexes: fights(status), fights(createdAt), bots(eloRating), payments(status)
  • PRAGMA optimize on daily cron
  • Connection pool size: 1 writer + 4 readers (via better-sqlite3's sync nature this is automatic, but verify no concurrent write contention)

P2.4 Server Memory Leak Hunt

  • Run fight-loop for 4 hours, capture heap snapshots at 0h, 1h, 2h, 4h
  • Check for: unclosed SSE streams, orphaned fight event listeners, growing caches
  • Add process.memoryUsage() to admin stats endpoint
  • Set up --max-old-space-size=256 in Docker CMD as safety net

Month 3 Performance Tasks

P3.1 FightScene Split Enables Dead Code Elimination

  • After Week 9 split, unused choreography modules can be tree-shaken
  • Vite dynamic imports for choreography categories (load on demand)
  • Split point: import('./choreography/food.ts') only when food moves are picked

P3.2 CDN & Caching Strategy

  • Static assets: immutable hash filenames, Cache-Control: max-age=31536000
  • API responses: Cache-Control: no-store for fight data, max-age=60 for leaderboard
  • Service worker: Stale-while-revalidate for sprites/audio
  • Compress all API responses with gzip (Hono middleware)

P3.3 Load Test Results → Optimization

  • Profile under simulated 100-spectator load
  • Identify: SSE fan-out bottleneck, DB query hotspots, memory ceiling
  • Optimize based on actual profiling data, not guesses
  • Document capacity ceiling: "This VPS handles X concurrent fights with Y spectators"

P3.4 Production Monitoring

Files: server/src/engine/analytics.ts

  • Log slow queries (> 50ms) to structured log
  • Track: p50/p95 fight duration, webhook response latency, payment settlement time
  • Memory/CPU metrics every 60s to analytics table
  • Alert threshold: memory > 200MB, fight error rate > 5%, payment failure > 1%

Mobile-Specific Performance

Touch & Rendering

  • Canvas rendering: limit to 30fps on mobile (save battery), 60fps on desktop
  • Disable parallax scrolling and complex CSS animations on mobile
  • Use will-change: transform sparingly (GPU memory cost)
  • Intersection Observer for off-screen fight cards (don't render invisible content)

Network

  • Preconnect to API server: <link rel="preconnect">
  • Prefetch next likely page (e.g., fight card → fight page)
  • Compress SSE payloads (only send changed fields, not full state)
  • Offline-first: service worker serves cached shell immediately

Dependency Graph

Month 1                          Month 2                        Month 3
───────                          ───────                        ───────
W1 Spectating ──────────────────────────────────────────────── W9 FightScene Split
W2 Betting UI ──┐                                              W10 Performance
W3 Nostr Social │               W5 Tournaments ──────────────── W11 Admin
W4 Seasons ─────┤               W6 Human Play                  W12 Launch
                │               W7 Content ─────────────────── W12 Launch
                └──────────────→ W8 Choreography ─────────────→ W9 FightScene Split
  • Weeks 14 are mostly independent of each other (parallelize)
  • Week 5 (Tournaments) needs Week 2 (Betting) for entry fees
  • Week 6 (Human Play) needs Week 1 (Spectating) for live sync
  • Week 9 (Split) should happen after Week 8 (Choreography) to avoid splitting then adding
  • Week 12 (Launch) needs everything

Risk Mitigation

Risk Mitigation
FightScene.ts too fragile to split Comprehensive replay testing before/after; git branch for safe rollback
SQLite bottleneck under load WAL mode + connection pooling; monitor write contention; Turso migration path if needed
NWC wallet failures Graceful fallback to Cashu; refund queue for stuck payments
Choreography visual bugs Automated screenshot comparison for 20 reference fights
Scope creep Each week is self-contained; can ship at end of any week

Success Metrics (End of Month 3)

Content:

  • 500+ choreographies, 2,000+ challenge prompts, 40 arenas, 20 music tracks

Adoption:

  • 10+ real bot developers registered and competing
  • Tournaments running daily with real sats
  • Betting volume: 10,000+ sats/day
  • Mobile PWA installs > 0 (any adoption = success for v1)

Reliability:

  • Zero stuck fights, zero lost payments over 7-day period
  • Fight loop stable for 72hr continuous operation

Performance:

  • Initial bundle < 300KB gzipped (excluding lazy-loaded TTS)
  • Time to first fight frame < 2s on 4G mobile
  • 50-fight replay session with flat memory (no leaks)
  • Server stable at < 250MB RSS after 24hr fight-loop
  • 20 concurrent fights + 100 spectators without degradation
  • Docker image stays < 50MB
  • SQLite handles 10K fights without query degradation (< 50ms p95)