Play classic board games, puzzles, and real-time arcade duels peer-to-peer with a friend over WebRTC โ or solo vs a bot. Plus a Tools drawer of game-night utilities and a fully synthesized soundtrack. No backend, no build step, no sign-up, no bundled assets to license. Installable as an offline PWA.
2 players ยท peer-to-peer ยท no sign-up
- ๐น๏ธ 50 games across Classic ยท Strategy ยท Puzzle ยท Arcade ยท Luck ยท Word โ from Chess and Go to Tetris, 2048, and newcomers Notakto, Domineering, Lights Out, and Word Ladder.
- ๐ฅ Three ways to play โ P2P vs a friend (all games, over WebRTC), vs Bot (~42 games, easy/medium/hard), or Solo (2048, Tetris, Snake, Minesweeper, Sudoku, Word Race, Match3, Level-2048, Lights Out, Word Ladder).
- ๐งฐ Tools drawer โ non-game utilities for game night: dice roller, coin flip, countdown timer, a persistent scoreboard, and a random name / team picker.
- ๐ Game of the Day โ one deterministic pick, the same for everyone, refreshed daily on the home screen.
- ๐ Find players online โ a lightweight public directory (MQTT) lets you see others, invite, and play; the match itself stays peer-to-peer.
- ๐ No server, secrets stay local โ for Number Duel / Battleship your hidden state never leaves your device; peers only exchange move feedback.
- โป๏ธ Resilient matches โ either player can Pause; a drop auto-pauses and auto-resumes on rejoin; a refresh restores your board & history (within ~30 min).
- ๐ Switch games without leaving the room and pick the first-move rule (coin toss / host first / loser first).
- ๐ Learn any game โ a How to play panel with a looping CSS/JS demo of the mechanic; ? reopens it mid-game.
- ๐ English / ุงูุนุฑุจูุฉ (RTL), ๐ fully synthesized audio โ Web Audio sound effects and generative ambient music, no audio files shipped โ plus a profile / leaderboard / loyalty system (levels, coins, rating) and 9 accent themes.
- ๐ฑ Installable PWA โ works fully offline after first load.
flowchart LR
A([Player A]) <-->|WebRTC data channel ยท PeerJS| B([Player B])
A -. presence/invites only .-> M[(Public MQTT broker)]
B -. presence/invites only .-> M
subgraph Engine["js/platform.js โ game-agnostic shell"]
P[home โ connect โ lobby โ toss โ play โ over]
end
A --- Engine
B --- Engine
js/platform.js is a game-agnostic engine: it handles the connection, lobby, coin toss, turns/timer, pause-resume, and solo/bot loopback. Each game is a small module under js/games/ that plugs into a shared lifecycle API (start, onMessage, onTurn, endGame, plus botMove for bot play). Pure rules live in js/logic.js; every game is registered in js/app.js.
Tech: vanilla JS ES modules (no build) ยท Tailwind via CDN ยท PeerJS (WebRTC) ยท MQTT.js (presence) ยท Canvas for real-time games ยท service worker for offline. Deploys to GitHub Pages.
ES modules + WebRTC need http://localhost (not file://). From the repo root:
git clone https://github.com/hassanannajjar/dual_game.git
cd dual_game
python3 -m http.server 8000Open http://localhost:8000/ in two browser windows to play both sides. One creates a room and shares the code (or a deep link โฆ/?g=<game>&room=<CODE>); the other joins.
Run the logic self-check:
node test.mjsDeploy: push to GitHub Pages (root, main) โ .nojekyll is included so js/ is served as-is. Live pattern: https://hassanannajjar.github.io/dual_game/.
Before a deploy, bump the cache-buster + service-worker version:
./bump-version.sh 49 # rewrites ?v= tags and the SW cache name (currently v48)Show all 50 โ Classic ยท Strategy ยท Puzzle ยท Arcade ยท Luck ยท Word
Number Duel ยท Tic-Tac-Toe ยท Connect Four ยท Rock Paper Scissors ยท Battleship ยท Gomoku ยท Reversi ยท Checkers ยท Dots & Boxes ยท Ultimate TTT ยท Mancala ยท Memory ยท Nine Men's Morris ยท Chess ยท Hangman ยท Snakes & Ladders ยท Pig ยท Go ยท Order & Chaos ยท Nim ยท Yahtzee ยท Hex ยท Ludo ยท Backgammon ยท Chinese Checkers ยท 2048 ยท Tetris ยท Air Hockey ยท Tron ยท Minesweeper ยท Snake ยท Sudoku ยท Sim ยท Wordle Duel ยท Farkle ยท Quarto ยท Mastermind ยท Dominoes ยท Word Race ยท Match3 ยท Pentago ยท Breakthrough ยท Lines of Action ยท Onitama ยท Quoridor ยท Level 2048 ยท Notakto ยท Domineering ยท Lights Out ยท Word Ladder
(bold = real-time arcade duels; italic = added in the latest update; the canonical list + categories live in js/app.js)
dual_game/
โโโ index.html # app shell: home grid, lobby/connect/play screens, CDN deps
โโโ app.css # neon theme layered on Tailwind CDN
โโโ js/
โ โโโ app.js # entry โ registers all 50 games + categories, boots the app
โ โโโ platform.js # engine โ connection, lobby, toss, turns, pause/resume, bot/solo, Game of the Day
โ โโโ logic.js # pure game rules (shared, unit-tested)
โ โโโ games/*.js # one module per game
โ โโโ tools.js # non-game utilities (Tools screen)
โ โโโ presence.js # MQTT online directory + leaderboard
โ โโโ i18n.js ยท sound.js ยท profile.js ยท loyalty.js ยท demos.js # subsystems (sound.js = SFX + generative music)
โโโ sw.js # service worker โ offline app shell
โโโ manifest.webmanifest # PWA install metadata + icons
โโโ bump-version.sh # release: bump ?v= tags + SW cache
โโโ test.mjs # Node self-check (logic + EN/AR i18n parity)
โโโ CONTRIBUTING.md ยท CLAUDE.md # the golden rules
โโโ .github/workflows/ci.yml # CI: runs node test.mjs
New game? The whole recipe is in docs/ADDING_A_GAME.md.
- Strict NATs may fail. PeerJS uses free public signaling with no TURN relay, so some corporate/mobile networks can't establish the P2P link.
- Trust-based. There's no server referee โ peers exchange moves directly, so it assumes a friendly opponent.
- Resume window. Refresh-resume works per-browser for ~30 minutes.
- Online presence isn't private. The public MQTT "circle" is best-effort and visible to anyone on that broker โ use a non-obvious circle name for a private group.
- Music is generative, not curated. The default soundtrack is synthesized ambient (no files). Prefer your own tracks? Drop rights-cleared MP3s in
audio/and list them inaudio/tracks.json.
MIT ยฉ 2026 Hassan Al-Najjar. No third-party assets are bundled โ all sound and music are synthesized at runtime โ so the repo is clean to fork, host, and redistribute. Contributions welcome: see CONTRIBUTING.md.
A personal, for-fun project. Peer-to-peer play is unmoderated and trust-based (no server referee).


