- Allow huggingface.co in CSP connect-src (fixes Kokoro TTS model download)
- Add registerSW.js route (fixes PWA service worker 404)
- Add _resetPositions() safety after entrance (fixes invisible fighters)
- Fight end sequence works without canvas scene (KO/overlays/log always play)
- Pre-fight instructions in battle log for human players
- NIP-55 visibility sync and cleanup handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security:
- Move CREATOR_PUBKEY from hardcoded constant to BOTFIGHTS_CREATOR_PUBKEYS
env var. Shared isCreatorPubkey() in constants.ts used by auth, admin,
tournaments. Frontend checks authorization via API, not client-side.
Mobile fixes:
- Nostr signer: poll for window.nostr up to 3s (Amber injects late).
- TTS: auto-unlock AudioContext on first user interaction via
installAutoUnlock() on fight page mount.
UX:
- Add loading spinners to "I BUILD BOTS" and "I FIGHT MYSELF" buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Nostr signer: poll for window.nostr up to 3s on mobile (Amber injects
late). Both login() and handleSignerLogin() now wait before failing.
- Mobile TTS: install global one-time click/touch/keydown handler to
auto-unlock AudioContext when fight pages mount. Previously only
triggered by explicit sound toggle, so mobile TTS silently failed.
- Add loading spinners to "I BUILD BOTS" and "I FIGHT MYSELF" buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove .slice(0, 120) truncation from battle log entries and
.slice(0, 60) from speech bubble calls. Increase bubble limits
to 200 chars, 24 chars/line, 8 lines so responses display fully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix invisible characters in human mode: init live scene BEFORE starting
challenge polling so entrance plays before first question appears
- Cap creative writing timer to 10s for multiple choice (just tapping buttons)
- Fix TTS reliability: precache priority phrases (Round 1-7, Fight!, K.O.)
all at once instead of in slow batches; prevent duplicate precache runs
- Add 10 vibe-coded narrations (~20% chance): "I was vibe coded into existence"
- Add 15 sweary narrations (~30% chance): raw unhinged fight commentary
- Add sweary draw and retro narrations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
All pages used h-[calc(100dvh-4rem)] which only subtracted the top
navbar but ignored the mobile tab bar's pb-14 bottom padding, causing
content to overflow and scroll. Changed all pages to h-full so they
fill the flex parent (main element) which already handles both the
navbar and tab bar spacing correctly.
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>
Split FightPage.vue into useFightPolling (SSE, polling, reconnect)
and useHumanChallenge (timer, submission, cooldown) composables.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- FightPage.vue: store SSE listener refs in array, removeEventListener
on each before close() in disconnectSSE()
- FightScene.ts: add cleanupTimers Set with trackedInterval/trackedTimeout
helpers; replace key setInterval calls (projectile trails, entrance
flames, talking animation, exhaust effects, dimensional shift, hole
fade) with tracked versions; clear all on scene destroy()
- rate-limit.ts: export cleanupInterval handle for graceful shutdown
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>
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>
- 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>
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>
All empty catch blocks across 8 Vue pages now log warnings. User-initiated
actions (fight, matchmake) also surface errors in the UI via fightError/loadError refs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add route param watcher so navigating to a new fight properly resets
and reinitializes the scene (fixes KAPLAY re-init / null scene errors)
- Add loading spinner to profile page instant fight button
- Restore truncated challenges.ts (was causing all 500 errors)
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>
- Add scale factor (SF) based on canvas height so bots and referee
shrink proportionally on small screens (reference: 500px)
- Scale judge chair/ladder dimensions with SF
- Push judge seat lower on small canvases so it stays visible
- Use 100dvh instead of 100vh to account for mobile browser chrome
(address bar, tab bar) — eliminates scroll under browser UI
- App root uses dvh, main area uses min-h-0 + overflow-y-auto
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>
- Remove stray duplicate template block outside TEMPLATES array that caused parse error preventing server startup (fixes /api/queue/status 500)
- Add choices field to Challenge/PromptEntry interfaces for multiple choice support
- Allow voice lines to overlap naturally instead of cancelling previous speech on every call, with safety flush at depth > 3
- Buffer challenges during cooldown in polling path, auto-submit random choice on timeout
- Block auto-battle for human fights, guard replay-done auto-transition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Buttons always side-by-side with shorter labels (FIGHT / WATCH)
- Hero bots displayed horizontally below title on mobile
- Desktop keeps flanking hero layout with larger sprites
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Canvas takes top 60%, controls panel takes bottom 40% on mobile
- Battle log header/text hidden on mobile, controls always visible
- Multiple choice buttons shown on both mobile and desktop
- Removed canvas overlay approach in favor of proper split layout
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 SSE human_challenge listener for instant input activation with auto-focus
- Buffer challenges during 3s round cooldown, apply with correct remaining time
- Map 'human' archetype to fighter-looking archetypes (boxer, ninja, etc.) in sprite system
- Show challenge questions in battle log via round_start SSE events
- Ensure human players are always botA (left side) in queue matchmaking
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 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>