- Fix fight replay showing empty scene: validate rounds before playing,
retry loading fight data up to 5 times when rounds are missing
- Add COOP/COEP headers to production server for SharedArrayBuffer
(required by Kokoro TTS WASM threading on mobile)
- Add blob: to scriptSrc/workerSrc CSP for Web Worker support
- Fix mobile character cutoff: raise ground line to 0.82, add
MOBILE_SCALE_CAP (0.55) so fighters never shrink too small
- Add ₿ bitcoin chest badge to all fighter sprites (scales with tier)
- Add sats coin stack on bot profile page proportional to satsWon
- Seed dev tournament with 8 mock bots on startup (dev mode only)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace any[] with GameObj[], fighter: any with Fighter in speech
bubbles, talking anims, showboat system, bow/fistbump/helpup, and
dizzy stars. Fix customization as any casts with ?? undefined.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move FightData, FightRound, FightBot, FightArenaInfo types from local
definitions in FightViewer.vue to shared fight/types.ts. Replace `any`
typing in HumanFightPage, FightPage, useFightPolling, and useFightCache
with proper typed interfaces. Fix null-safety guards exposed by typing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Normal wins: winner flex pose with camera flash bursts + confetti rain.
Upset wins (100+ Elo underdog): dramatic zoom on winner with golden
flash. Upset tag shown on win overlay. Wired into FightViewer after
KO/Perfect sequence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TournamentListPage with status filters, TournamentPage with CSS grid
bracket display, lobby view for open tournaments, champion banner,
live polling for active tournaments. Routes at /tournaments and
/tournament/:id. NavBar link added.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CacheFirst runtimeCaching rules for Hugging Face model requests
(huggingface.co and cdn-lfs) with 90-day expiration. Add
getKokoroProgress() export to tts.ts for tracking download progress.
Add TTS model download progress bar overlay in FightViewer.vue that
shows during model loading and auto-hides when complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ZAP WINNER button in FightViewer after fight ends. Server endpoint
POST /api/payments/zap increments zapsReceived on winner bot. Show zap
count on bot profile page. Add zaps_received column with migration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BetHistory component shows personal bet history with fight links,
amounts, outcomes, and payouts. P&L summary shows total wagered, total
won, and net sats. Added to BotProfilePage for the bot owner's view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BetPanel component with pick-winner buttons, preset amounts (21/100/500/
1000 sats), Cashu token paste, odds display from server, and payout
preview with 5% house cut. Wired into FightCardPage for scheduled fights.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
POST /api/fights/:fightId/react endpoint accepts emoji reactions (fist,
fire, skull, 100, clown), aggregates counts, broadcasts via SSE.
Reaction bar added to FightViewer with floating emoji particles that
rise and fade. Live fight views receive reactions via SSE in real-time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverse-chronological activity stream of recent fights showing winner,
KO/decision result, arena, sats, and time ago. Filter by tier and bot
name. Click any fight to watch replay. Added to NavBar as FEED link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Comedy sounds (all procedural Web Audio, no samples):
- Vine Boom, Air Horn (MLG), Bruh, Fart, Record Scratch
- Rubber Chicken, Squeaky Toy, Wet Slap, Bone Crack, Cartoon Run
- Rim Shot (ba dum tss), Slide Whistle Up/Down, Yippee, Ding
- Taco Bell Bong, Windows Error, Meme Thud
- Sad Trombone, Emotional Damage, Dun Dun Dunnnn
- Fail Horn, Price Is Right Fail, Buzzer, Sad Violin
- Mission Failed, Crickets
Wiring:
- Round-end narration: 75% comedy SFX, 25% TTS (was 100% TTS)
- Critical rounds get Emotional Damage, draws get random fail
- Showboat loop: 40% chance of comedy sound punctuation after each
- KO finish: 50% chance of comedy fail sound on loser
- sfxRandomSilly expanded with comedy sounds
- New exports: sfxRandomComedy, sfxRandomFail
Also adds bulletTimeAttack combat choreography + ultimateBulletTimeBarrage
(tier 3+ ultimate) to fight system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fighters now perform random showboating micro-animations while idle
during question reading and opponent's answer — shadow boxing, backflips,
flex poses, moonwalks, ground pounds, air guitar, sumo stomps, and more.
Each showboat uses existing sprite anims (attack/kick/special/win) combined
with Kaplay tweens for position, scale, rotation, sparks, and emote text.
Showboating loops with random variety and pauses between moves.
Flow: both showboat during question → stop the answering bot during their
turn → stop all before fight animation begins.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Unified speakAsync/speakAsyncWithRate into _speakAsyncCore with:
- 500ms startup check: bail immediately if speech won't start (mobile/no gesture)
- 8s safety timeout (down from 15s) to prevent blocking
- iOS-safe keepalive: only do Chrome pause/resume workaround on desktop Chrome
- Immediate bail when no voices loaded
- Sprite loading: 5s timeout per sprite prevents mobile hangs from stuck Image decodes
- Scene creation: 10s timeout in FightViewer so overlay/voice flow continues even if
canvas fails on mobile
- playRound: bail gracefully if fighter sprites missing instead of crashing
- Global audio unlock: first touch/click on site unlocks AudioContext + SpeechSynthesis
- Practice button pre-unlocks audio while still in user gesture context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TTS fixes:
- Remove 60-char truncation in FightViewer — let speakAnswer handle limits
- Smart truncation at sentence boundaries (period, comma, etc.) up to 200 chars
- Chrome keepalive: periodic pause/resume prevents silent 15s cutoff bug
- Deduplicated cleanup logic in speakAsync/speakAsyncWithRate
Retro mode:
- Simplified challenge prompt from verbose wall of text to clean 3-line format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every fight now includes one Retro Mode round where bots submit
gamepad combo inputs (↑↓←→ A B). 24 moves across 4 tiers: basic
(always shown), standard (partially revealed), super (must discover),
and ultra (KONAMI CODE for 50 dmg). Discovery bonus gives 1.5x damage.
Includes pixel-art gamepad overlays (P1/P2) with animated button
presses, retro-specific narrations, and mock bot combo responses
scaled by ELO.
Also adds loops/plan.md with 11-phase production hardening roadmap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fight Card page: dramatic poster background with cross-hatch, spotlights,
vignettes, corner brackets, scan lines; 3D VS orb with punch animation;
selectable undercard with main event always pinned at top
- PosterSprite: high-quality 480px poster frame with 6-pass renderer
(aura, glow, bevel, specular, particles); PixelGlove component
- 12-char bot name limit across all forms and server validation
- Mock bots: all 100 now have diverse archetypes (25 types), 25% human
fighters; seedMockBots updates existing bots on restart
- Leaderboard: inline SpritePreview next to each bot name
- Nostr auth: persistent login, nsec copy button
- Wallet: NWC + Lightning Address, ranked fight flow
- Server: payments, ranked queue, customization endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Arena page shows small sprite previews next to each bot's name
- Server returns archetype in fights list endpoint
- New /fight-card page with 3D perspective fight poster, neon signs,
animated boxing gloves, fighter bobbing, VS pulse, undercard list
- Added FIGHT CARD to nav bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add WalletConnect.vue with NWC/LN Address connection states. Add "FIGHT
FOR SATS" button to JoinBoutPage with entry fee payment flow. Show ranked
pot and winner payout in FightPage. Add sats stats and wallet section to
BotProfilePage. Extend BotData interface with satsWon/satsWagered/hasWallet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FightViewer: wrap createFightScene in try/catch so scene failures
don't crash every subsequent playRound call
- FightViewer: wait for container to have non-zero dimensions before
creating canvas (prevents 0x0 canvas causing sprite load failures)
- FightViewer: graceful log-only fallback when scene init fails
- FightPage: same dimension-wait and try/catch for initLiveScene
- Fallback canvas dimensions (800x500) when container not yet laid out
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetches from /api/docs/webhook and renders as a styled tabbed page.
Added /docs route and DOCS nav link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FightViewer: track deferred speechSynthesis.cancel() timer, clear on unmount
- BotProfilePage: change isOwner from ref to computed for reactive login state
- sounds.ts: tighten speech queue depth cap from 3 to 2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ArenaPage: merge duplicate onMounted hooks into single parallel fetch
- FightPage: queue SSE events until liveFightData ready, add reconnect with backoff
- FightViewer: fix stale canvas ref with container ref, add sceneReady guard
- HomePage: replace stopCycling boolean with AbortController for clean unmount
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Canvas 50% top, battle log 50% bottom on mobile
- Add overflow-hidden to prevent page scrolling past viewport
- Bots no longer cut off with more canvas space
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Canvas takes 30% top, battle log + human input takes 70% bottom on mobile
- Battle log now visible on mobile for both live fights and replays (was hidden)
- Compact single-row health bar on mobile to maximize canvas space
- Desktop layout unchanged (62/38 split)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Server-side choice generation for all 22 challenge types (factual + creative)
- Mobile: 3 multiple-choice buttons replace keyboard input (4s timer)
- Two-row VS bar on mobile (names row + HP bars row) in FightPage and FightViewer
- Battle log hidden on mobile to maximize canvas visibility
- Arena page responsive: stacking header, tighter fight cards, no name overflow
- Profile page two-column desktop layout with contained sprite display
- Human fighter sprites with baby growth system
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add choose-mode step: "I BUILD BOTS" vs "I FIGHT MYSELF" paths
- Human registration with baby avatar picker, no webhook required
- Live fight scene with SSE round streaming and real-time challenge UI
- 5-second timer per round, submit answers via browser
- Baby → toddler → kid → teen → adult → hero → super growth stages
- Huge sparkly baby eyes, diapers, pacifiers, bibs, rattles, rosy cheeks
- Speech bubble positioning fix (pushed to outside of sprite)
- Canvas text rendering via offscreen canvas to bypass kaplay color issues
- Voice timing improvements: await pauses between voice lines and hits
- 30 devastating announcement lines, 15 critical/hit word variants
- Orchestrator human player detection + waitForHumanResponse system
- Server endpoints: GET /challenge/:botId, POST /respond/:botId
- Human player auth: register-human route, isHuman flag on login
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change speak() default to cancelPrevious=true so voices don't queue endlessly
- Add stopAllAudio() export and wire into FightViewer unmount + post-fight
- Flush speech queue at fight end with delayed cancel for clean cutoff
- Expand from 30 to 60+ voice profiles (robots, accents, game, characters)
- Add speech bubbles showing bot responses during rounds
- Wire announceFinishHim/Fatality/FlawlessVictory/Devastating to not cancel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Dockerfile (multi-stage: build frontend + server, serve from single container)
- Add docker-compose.yml for Portainer stack deployment
- Server serves frontend SPA in production (static assets + SPA fallback)
- Auto-run migrations and seed mock bots on server startup
- DB path configurable via DB_PATH env var
- Add "Fight a Classic Bot" button for instant mock bot matches
- FIGHT button queues for real AI opponents
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Large animated sprite on BotProfilePage with tier-aware rendering
- Dynamic status titles (UNSTOPPABLE, ON FIRE, FRESH MEAT, etc.)
- Nostr auth persisted to localStorage — survives navigation and HMR
- Remove grotesque close-up overlays (eyeballs, tongues, teeth, drool)
- Remove crowd cheering signs (too small to look good)
- Add archetype to bot stats API response
- SpritePreview now accepts tier prop
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .run() to all Drizzle queries inside sqlite.transaction() in
orchestrator.ts and mock.ts — queries were building but never executing,
leaving fights stuck as 'live' forever
- Remove spectator crowd from drawArenaDecor()
- Rename duplicate spawnProp to spawnWeaponProp (was crashing module load)
- Replace canvas element on re-init to avoid "KAPLAY already initialized"
- Add safeText() to strip brackets from k.text() calls (Kaplay treats
[ ] as style markup, crashes on unclosed tags)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fight loop CLI with TUI renderer (ink-style terminal UI)
- Rate limiting middleware for API routes
- Queue cooldowns wired into orchestrator after fights
- Webhook test utility for bot debugging
- API docs route
- Expanded FightScene choreographies and weapon props
- Fix Drizzle transaction execution in orchestrator
- Schema additions, scoring/challenge/mock expansions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add fight-loop CLI for automated mock fights with elo-based matchmaking
- Expand challenge types, scoring narrations, arenas, and mock bot pool
- FightPage "Fight again" buttons now only show for your own bot
- FightViewer async scene init, live fight polling with round counter
- Extract mock answers into separate answers module
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Vue 3 + Vite + Tailwind 4 frontend with synthwave aesthetic
- Hono backend on port 9100 with SQLite/Drizzle
- Procedural pixel-art sprite generator (48x48, 8 animation states)
- Kaplay fight scene with punch/kick/special/knockback/KO animations
- 12 mock bots across 6 tiers with Elo rating system
- 9 challenge types, 10 fight arenas with modifiers
- Fight replay with staggered battle log and ~1 min timing
- Sprite preview page at /sprites
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>