Overview
LennyFighter is built entirely on Cloudflare's developer platform, running at the edge with zero origin servers.
Architecture
- Vinext (Cloudflare's React SSR framework)
- Cloudflare Workers (edge runtime)
- Durable Objects: MatchmakingQueue (pairs players), MatchRoom (battle state)
- D1 (SQLite database for player stats, LennyCoin balances, item inventory)
- KV (session token cache with 1-hour TTL)
- WebSockets for real-time multiplayer with KV-backed token auth
Architecture Diagrams
Click each diagram to expand.
Tech Stack
Framework: Vinext (React SSR on Cloudflare Workers)
React: React 19 with React Server Components
Build: Vite 8
Runtime: Cloudflare Workers
Multiplayer: Durable Objects + WebSockets
Database: Cloudflare D1 (SQLite)
Session Cache: Cloudflare KV
Game Engine: Pure HTML/CSS + React (no canvas/Phaser)
Matchmaking: MatchmakingQueue DO (singleton)
Match State: MatchRoom DO (one per match)
Security
- KV-backed session tokens for WebSocket authentication
- Server-side damage calculation (clients cannot send arbitrary damage values)
- Parameterized SQL queries for all D1 operations
- Atomic LennyCoin transfers via D1 batch transactions
- Fighter ID validation against server-side roster (clients cannot inject arbitrary stats)
- Anti-spam turn locking prevents duplicate answers per turn
Multiplayer Infrastructure
- MatchmakingQueue is a singleton Durable Object that pairs players using level-based matching (within 3 levels, FIFO fallback) with a 3-second alarm retry cycle
- MatchRoom is a per-match Durable Object that holds authoritative battle state, processes turns, validates moves, and records results
- If a player disconnects, they get a 20-second reconnection grace period before the match is forfeited
- WebSockets use hibernatable mode so idle connections do not consume billable duration
- A wager negotiation phase lets both players bet LennyCoin before combat (15-second timeout, skipped if either has 0 LC)
- An item selection phase occurs before the first turn when items are enabled (15-second timeout)
Data Model
- KV: Session tokens (keyed by UUID, value is gamertag, 1-hour TTL)
- D1: Player registration (
players), win/loss stats and LennyCoin balances (player_stats), item inventory (player_items) - DO memory: Ephemeral match state (HP, turns, trivia, wagers) — not persisted after the match ends
- Client storage: Gamertag in localStorage; session token, active match info, and bot match state in sessionStorage