A modern, browser-based implementation of the classic Dots and Boxes game (reimagined as ShapeKeeper) with adaptive landscape layouts, smooth animations, and touch support.
Play Now: https://shape-keeper.vercel.app
- Classic Dots and Boxes mechanics - Connect dots to create boxes and score points
- Diagonal Lines - Connect dots diagonally for alternative paths
- Two-player turn-based gameplay - Players alternate turns, with bonus turns for completing shapes
- Turn-Based Online Multiplayer - Chess-like communication with Convex backend
- Live Lobby + Invite Link - Real-time waiting room with a shareable
?join=…&passcode=…URL and a one-tap copy button - Silly [Adjective][Animal] passcodes - Lobby auth codes like
EasterPigandSillyRabbit, dynamically generated per room (no env, no random letters, no numbers) - Opponent Tap Mechanic (multiplayer) - Tap an opponent's completed box to drop its multiplier from 2x → 0.5x before they reveal. Real-time hand-eye coordination layer on top of turn-based play.
- Smart turn logic - Complete a square, keep your turn!
- Real-time score tracking - Live updates for both players
- Party Mode 🎉 - ALL squares have tile effects (dares, hypotheticals, powerups, traps)
- Adaptive Landscape Layout - Automatically optimizes grid for landscape displays (e.g., 30x30 becomes ~50×18)
- Miniaturized Design - Dots are 5× smaller than traditional implementations for more gameplay area
- Smooth Animations - Particle effects and shape completion animations
- Pulsating Lines - Visual feedback for newly drawn lines
- Touch Visuals - Ripple effects for touch interactions
- Color Customization - Choose your own player colors
- Motion Trails - Particles leave fading trails for persistence of vision
- Ambient Particles - Floating background particles create atmosphere
- Dynamic Background - Gradient shifts based on game state
- Screen Shake - Feedback on multi-shape completions
- Combo System - Visual escalation for consecutive shape completions
- Victory Fireworks - Celebratory effects when game ends
- Dark Mode - Toggle between light and dark themes
- Procedural Sound Effects - Web Audio API generates all sounds (no audio files)
- Line Draw Sounds - Ascending tones when connecting dots
- Square Completion Chords - Harmonious feedback on scoring
- Combo Arpeggios - Musical escalation for streaks
- Victory Fanfare - Celebratory melody at game end
- Sound Toggle - Enable/disable audio with persistent preference
- Convex Backend - Real-time multiplayer with ACID transactions
- Vercel Deployment - Edge network for low latency globally
- Pure Vanilla JavaScript - No frontend frameworks
- HTML5 Canvas Rendering - Smooth, hardware-accelerated graphics
- Multi-touch Support - Native touch handling for tablets and phones
- Responsive Design - Adapts to any screen size
- Fullscreen Mode - Immersive gameplay experience
- Landscape Optimization - Best experience in landscape orientation
# Using Python 3
python -m http.server 8000
# Using Node.js (with http-server)
npx http-server
# Using PHP
php -S localhost:8000Then visit http://localhost:8000 in your browser.
game.jsandwelcome.jsare loaded as browser ES modules, so openingindex.htmldirectly withfile://is no longer a supported startup path.
Visit https://shape-keeper.vercel.app.
Important: All commands must run from the
ShapeKeeper/directory (wherepackage.jsonandconvex/live), not the repo root. Runningvercelorconvexfrom the root fails or deploys the wrong folder.
- A linked Vercel project (
shape-keeper) and Convex project (shapekeeper). - Local
.env.localwithCONVEX_DEPLOYMENT/CONVEX_DEPLOY_KEYfor the dev backend (oceanic-antelope-781) — used for local development only. - Production frontend is wired to the prod Convex backend
(
precise-ladybug-504.convex.cloud) viaconfig.js(no build step). Overridewindow.CONVEX_URLin a separate script BEFOREconfig.jsto point at a different deployment.
The deployment ships strict response headers via vercel.json:
- Content-Security-Policy:
default-src 'self';script-src 'self' https://unpkg.com;connect-srcrestricted to the Convex deployment;frame-ancestors 'none';object-src 'none'. Nounsafe-inlinefor script-src. - Subresource Integrity: the Convex browser bundle is loaded from
unpkg.com/convex@1.42.3with anintegrity="sha384-..."attribute. If unpkg is compromised or the package bytes change, the browser refuses to load the script. Bump the hash inindex.htmlwhen changing the version:curl -sSL https://unpkg.com/convex@<ver>/dist/browser.bundle.js | openssl dgst -sha384 -binary | openssl base64 -A. - HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, X-Frame-Options all set.
- HTML files are served with
Cache-Control: public, max-age=0, must-revalidateso deploys are picked up immediately;config.jsis cached 5 minutes.
cd ShapeKeeper
# 1. Deploy backend functions to the PROD Convex deployment
npx convex deploy --yes
# 2. Deploy the static frontend to Vercel (no build step; serves index.html as-is)
vercel --prod
# Local development (uses dev Convex backend via .env.local)
npx convex dev
npm run serve # python -m http.server 8000If you push main to GitHub, Vercel auto-deploys the frontend from this
directory. Backend changes still require npx convex deploy --yes.
The game offers four preset grid sizes that automatically adapt to your display:
| Selection | Square Mode | Landscape Mode* | Total Squares |
|---|---|---|---|
| 5×5 | 5×5 grid | ~7×4 grid | 16 squares |
| 10×10 | 10×10 grid | ~16×7 grid | 81 squares |
| 20×20 | 20×20 grid | ~33×14 grid | 361 squares |
| 30×30 | 30×30 grid | ~50×18 grid | 841 squares |
*Landscape mode activates when aspect ratio > 1.5
- Objective: Complete more squares than your opponent
- Turns: Players alternate drawing lines between adjacent dots
- Scoring: Complete a square by drawing its fourth side to earn a point
- Bonus Turn: Complete a square to earn another turn immediately
- Multipliers: Tap completed squares to reveal score multipliers
- Winning: Player with the most points when the grid is full wins
- Mouse: Click dots to select and connect them
- Touch: Tap dots on touchscreen devices
- Selection: Click a dot, then click an adjacent dot to draw a line
- Visual Feedback: Selected dot shows a colored ring
- Multipliers: Click/tap completed squares to reveal and apply multipliers
- Plan ahead to avoid giving opponents easy squares
- Try to complete multiple squares in one turn
- Control the endgame by managing available moves
- Watch for "double-cross" patterns
ShapeKeeper/
├── index.html # Main HTML structure (3-screen layout)
├── styles.css # Styling and responsive design
├── game.js # Browser module entry for the game runtime
├── welcome.js # Browser module entry for lobby/UI bootstrapping
├── dots-and-boxes-game.js # Main DotsAndBoxesGame class and orchestrator
├── convex-client.js # Convex browser API wrapper (~450 lines)
├── src/ # Shared ES6 modules used by the current runtime
│ ├── core/ # Constants, utilities
│ ├── game/ # Game state, input, multipliers
│ ├── effects/ # Particles, tile effects
│ ├── animations/ # Kiss emojis, square animations
│ ├── sound/ # Web Audio API SoundManager
│ └── ui/ # Theme manager
├── convex/ # Convex backend
│ ├── schema.ts # Database schema (rooms, players, lines, squares)
│ ├── rooms.ts # Room management functions
│ └── games.ts # Game state functions
├── docs/ # Documentation
│ ├── development/ # QUICKSTART, CODE_AUDIT, MERGE_CONFLICT_GUIDE
│ ├── planning/ # JOBCARD, CounterPlan, MULTIPLAYER_PLANNING, REFACTORING_PLAN
│ ├── history/ # DEPLOYMENT_STATUS
│ └── technical/ # BENQ_FIX, FEATURE_SUMMARY, PERFORMANCE_IMPROVEMENTS
├── Triangle/ # Triangle feature planning
│ └── canvasBonusFeature.md
├── vercel.json # Vercel deployment config
└── .github/
└── copilot-instructions.md # Development guidelines
index.html is the browser entrypoint. convex-client.js is loaded as a
classic script so it can expose window.ShapeKeeperConvex, while game.js
and welcome.js are loaded as ES modules and serve as the authoritative
runtime entry scripts for the competition branch.
- State Management: Lines (Set), Squares (Object), Scores (Object)
- Rendering Engine: HTML5 Canvas with 60fps animation loop
- Event Handling: Mouse, touch, and resize events
- Game Logic: Square detection, turn management, win conditions
setupCanvas(); // Adaptive layout calculation
getNearestDot(); // Collision detection for dot selection
checkForSquares(); // Square completion detection
draw(); // Main rendering loop
animate(); // Animation frame management'1,2-1,3'; // Horizontal line from (1,2) to (1,3)
'1,2-2,2'; // Vertical line from (1,2) to (2,2)
'1,1-2,2'; // Diagonal line from (1,1) to (2,2)Always sorted to prevent duplicates.
'5,10'; // Square at row 5, column 10screenX = offsetX + col × cellSize
screenY = offsetY + row × cellSize- Origin: Top-left corner
- Grid: 0-indexed rows and columns
Edit index.html to add new grid size buttons:
<button class="grid-btn" data-size="40">40×40</button>In game.js constructor:
this.dotRadius = 1.6; // Dot size
this.lineWidth = 2; // Line thickness
this.cellSize = 8 - 40; // Cell size range (calculated)Default colors can be changed in index.html:
<input type="color" id="player1Color" value="#FF0000" />
<input type="color" id="player2Color" value="#0000FF" />| Browser | Version | Status |
|---|---|---|
| Chrome | 90+ | ✅ Full Support |
| Firefox | 88+ | ✅ Full Support |
| Safari | 14+ | ✅ Full Support |
| Edge | 90+ | ✅ Full Support |
| Opera | 76+ | ✅ Full Support |
Requirements:
- ES6+ JavaScript support
- HTML5 Canvas API
- CSS3 (Flexbox, Grid)
- Opening
index.htmldirectly viafile://is not supported because the app boots with browser ES modules - Parsing error in VSCode is cosmetic (ESLint configuration)
- Portrait mode shows rotation prompt (landscape recommended)
- Very large grids (50×50+) may impact performance on older devices
- Multiplayer mode planning (see MULTIPLAYER_PLANNING.md)
- Online multiplayer with Convex + Vercel ✅
- Lobby system with room codes ✅
- Sound effects (procedural Web Audio API) ✅
- Dark/light theme toggle ✅
- Visual effects overhaul (CounterPlan complete) ✅
- Diagonal lines support ✅
- AI opponent with difficulty levels
- Game replay and save/load functionality
- Achievement system
- Custom grid size input
- Undo/redo moves
- Tutorial mode for new players
MIT License - feel free to use, modify, and distribute.
Teacher Evan
Created as an educational project demonstrating:
- Canvas API manipulation
- Game state management
- Responsive design patterns
- Touch event handling
- Animation techniques
Contributions welcome! Feel free to:
- Report bugs via Issues
- Submit pull requests
- Suggest new features
- Improve documentation
- Tap-to-collapse (multiplayer) - An opponent can now tap a completed box to drop its effective multiplier from the raw value (typically 2x) down to 0.5x before the owner reveals. The owner races to reveal; the opponent races to tap. Hand-eye coordination. See
docs/feature-opponent-tap.md. - Schema additions -
squares.taps(counter) andsquares.effectiveMultiplier(cached post-tap value). Old rows default to 0 / original multiplier. - Server validation -
tapSquarerejects self-taps, taps ontruthOrDaresquares, taps during the lobby, and taps on already-revealed squares. - Visual feedback - Red ✋ overlay on tapped squares (both players see it; disappears on reveal).
- Local hot-seat support - The tap is applied locally so the mechanic is testable without a backend.
- Silly [Adjective][Animal] passcodes - Lobby auth codes like
EasterPigandSillyRabbit, dynamically generated per room. Replaces the static-env and 6-letter-random-letter approaches. No numbers, no human names, no real places — seeconvex/rooms/shared.tsfor the word lists and the invariants inconvex/rooms/shared.test.js. - Live waiting room - New
LiveLobbyManager(src/ui/LiveLobbyManager.js) subscribes to Convex and renders the player list in realtime. Players see each other join without refreshing. - Invite link - New
🔗 Copy Invite Linkbutton on the lobby screen. Writes a${origin}/?join=ROOMCODE&passcode=PASSCODEURL to the clipboard. Falls back to a hidden readonly<input>+document.execCommandfor insecure contexts. - URL pre-fill - Loading the app with
?join=…&passcode=…jumps the user to the join screen with both inputs pre-filled. Documented indocs/feature-multiplayer-lobby.md. - Backwards compat - Legacy rooms (no
passcodefield) still allow code-only joining. Thepasscodecolumn isv.optional(v.string())so the schema change is non-breaking. - AGENTS.md - New file documenting the passcode rules + live-lobby invariants + repo conventions for future agents.
- Party Mode 🎉 - Renamed "Hypotheticals" to "Party Mode" - ALL squares have tile effects
- Turn-Based Multiplayer Optimization - Chess-like communication prevents glitches
- State Change Detection - Only updates UI when meaningful state changes occur
- Debounced Updates - Prevents rapid-fire updates from causing issues
- Documentation Index - Added docs/README.md for easy navigation
- Copilot Instructions Index - Table of contents for quick reference
- Squares-Only Gameplay - Triangle mechanics (added in v4.1.0) were removed; game is squares-only since v4.3.0
- Diagonal Lines - Players can connect dots diagonally at 45° angles
- Triangle Detection - Complete triangles by drawing 2 orthogonal + 1 diagonal line
- Dark Mode Canvas Fix - Canvas backgrounds now properly read theme state
- Triangle Scoring - Triangles worth 0.5 points (squares = 1 point)
- Triangle Visuals - Striped fill pattern distinguishes triangles from squares
- ES6 Module Structure - Partial refactoring to modular architecture
- Complete Visual Overhaul - All CounterPlan phases implemented
- Procedural Sound Design - Web Audio API sounds (no audio files)
- Dark Mode - Toggle theme with localStorage persistence
- Motion Trails - Particle persistence of vision effects
- Ambient Atmosphere - Floating particles, dynamic gradients
- Combo System - Visual escalation for consecutive squares
- Victory Fireworks - Celebratory particle effects
- Multiplayer Sync Fix - Multipliers synced from server
- Accessibility - ARIA labels, semantic improvements
- Online Multiplayer with Convex backend
- Lobby System with room codes for joining
- Vercel Deployment at shape-keeper.vercel.app
- CounterPlan visual evolution roadmap
- Real-time game state synchronization
- Removed zoom controls for simplified UI
- Added comprehensive multiplayer planning documentation
- Score multiplier system for completed squares
- Improved touch handling
- 5× smaller dots for better screen utilization
- Adaptive landscape layout optimization
- Enhanced touch support with visual feedback
- Improved animation system
- Performance optimizations
- Initial release
- Basic game mechanics
- Square grid layouts
- Mouse and touch support
Enjoy the game! 🎮✨
For questions or feedback, please open an issue on GitHub.

