Clon jugable en navegador de Dungeon Mayhem (Wizards of the Coast / D&D), multijugador de 2 a 4 jugadores en tiempo real. Next.js + un servidor de salas en tiempo real sobre Cloudflare Workers/Durable Objects, con las 28 cartas reales de 6 personajes (Misc, Sutha, Azzan, Lia, Oriax, Jaheira) y una interfaz estilo "juego de cartas profesional" (splash, menú, sala de espera, selección de héroe, tablero) con tema medieval/D&D y animaciones con Framer Motion. El tablero tiene un layout adaptado tanto a escritorio como a celular en vertical.
- Next.js (App Router) + TypeScript + Tailwind CSS v4 — frontend.
- partyserver (Cloudflare Workers + Durable Objects) — servidor de salas multijugador en tiempo real (WebSockets), desplegado con
wrangler. - Framer Motion — animaciones (splash, modales, volteo de cartas, transición de partida, paso de página del manual).
- nanoid — generación de códigos de sala.
pnpm install
pnpm dev # Next.js en http://localhost:3000
pnpm party:dev # Servidor de salas (wrangler dev) en http://127.0.0.1:1999 (en otra terminal)Sin party:dev corriendo, /room/[roomId] no podrá conectar (verás "Conectando a la sala..." indefinidamente).
Otros scripts: pnpm lint, pnpm exec tsc --noEmit, pnpm sim (juega 180 partidas aleatorias contra el motor puro y verifica que los detectores de animación coincidan con lo ocurrido — es la forma barata de comprobar que un cambio de UI no rompió las reglas), pnpm e2e (partidas reales por WebSocket contra el servidor de pnpm party:dev: reconexión, abandono, revancha), pnpm optimize:images (mueve el arte original a assets-src/ y genera el WebP servido en public/), pnpm party:deploy (deploy del servidor a Cloudflare Workers vía wrangler — no confundir con el deploy de Next.js/Vercel, que es aparte).
/ → Splash (logo + partículas, ~2s) → Menú Principal
├── Jugar (modal: nombre + Crear sala / Unirse por código) → /room/[code]
├── Colección → /collection → /collection/[characterId]
├── Cómo jugar → /how-to-play (libro paginado)
└── Ajustes (modal: música/sonido/volumen/idioma/pantalla completa)
/room/[roomId] → una sola conexión WebSocket durante todo el ciclo:
"waiting" Sala de espera (código, roster, anfitrión 👑)
"selecting" Elige tu héroe (cartas volteables, bloqueo sincronizado)
"playing" Tablero de la partida
"finished" Panel de victoria/derrota + Revancha
Ver CLAUDE.md para el detalle de arquitectura, y .claude/plans/ (si existe) o el historial de conversación para el plan original del rediseño.
src/lib/game/
types.ts Todos los tipos compartidos: efectos de carta, GameState/GameView, RosterEntry, ClientMessage
engine.ts Motor de combate puro (createPlayer, playCard, startMatchFromRoster, toView...)
characters.ts Los 6 personajes con sus mazos reales (28 cartas c/u) + ability/flavorText
party/server.ts Servidor (partyserver/Durable Object): roster/host antes de la partida, chooseCharacter/startMatch, playCard, rematch
src/components/
CardView.tsx Render de una carta (imagen real o fallback por iconos)
CardLightbox.tsx Modal de carta agrandada — tap en Colección, mantener presionado en el tablero (móvil, sin hover)
room/ GameBoard (con layout compacto para celular en vertical), WaitingRoom, CharacterSelect, CharacterFlipCard, MatchTransition
PlayModal.tsx, SettingsModal.tsx, ParticleField.tsx, BookReader.tsx
src/app/
page.tsx Splash + Menú
room/[roomId]/page.tsx Sala unificada (una sola conexión de socket)
collection/, collection/[characterId]/
how-to-play/
public/characters/<id>/cards/ Fotos reales de cartas, nombradas <Personaje>_<Nombre_Carta>.<ext>
public/lobby/, public/game/ Fondos de pantalla (menú, sala, tablero) + imágenes de victoria/derrota
public/audio/ Música (agregada, todavía sin reproducción conectada — ver Limitaciones)
Los 6 personajes tienen su mazo completo de 28 cartas con efectos reales (no son cartas genéricas). Reglas fieles al juego físico: roba 1 al inicio de turno, mínimo 1 carta jugada por turno, cadenas con ⚡ ("juega otra carta"), escudos que quedan en juego absorbiendo daño, mecánicas especiales por personaje (robar/destruir defensa, inmunidad temporal, daño a todos, Forma Oso/Lobo de Jaheira, etc. — ver EffectKind en types.ts).
Soporta salas de 2 a 4 jugadores: con más de un rival, las cartas que apuntan a un solo oponente (ataque, robar/destruir defensa, etc.) piden elegir objetivo en pantalla en vez de apuntar automáticamente. El tablero ubica al rival de arriba al centro y a un 2º/3er rival a los costados, igual en escritorio que en celular (en celular, más pequeños y sin el desfase fijo en píxeles pensado para pantallas anchas).
Al terminar la partida se muestra un cartel de Victoria/Derrota (imagen, no solo texto) con opción de Revancha o volver al lobby.
- Sin audio real. Ajustes tiene los controles (música/sonido/volumen) persistidos en localStorage; ya se agregó
public/audio/music-lobby.mp3, pero todavía no hay ningún<audio>/reproducción conectada a esos controles. - Sin reconexión. Si alguien refresca la página a mitad de sala/partida, no puede recuperar su asiento (nuevo
conn.id); simplemente se desconecta y el rival gana (si ya estaba jugando) o el roster se actualiza (si estaba en la sala de espera). - Servidor de salas ya desplegado (Cloudflare Workers, gratis — ver
CLAUDE.md); el frontend Next.js todavía no está desplegado a Vercel.