# Botfights: 6-Month Development Plan (March–September 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 0–6) | 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 0–2 fights), medium (3–4), hard (5–6) #### 7.2 Music Tracks → 20 **Files:** `frontend/src/game/sounds.ts` - 10 new procedural tracks: - 2x Drum & Bass (170–175 BPM) - 2x Lo-fi Hip Hop (90–100 BPM) - 2x Ska Punk (200–220 BPM) - 2x Boss Fight (140–160 BPM, heavy) - 2x Chiptune (180–200 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 0–1: 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: `` - 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 1–4 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)