An experimental online platform for playing Ban Chess, a chess variant where players alternate between banning opponent moves and making their own moves.
📖 For complete game rules, see RULES.md - the canonical ruleset for Ban-Chess.
Built with:
- Next.js 15.5.2 (App Router) — UI & routing with React 19
- @bezalel6/react-chessground — interactive chessboard
- ban-chess.ts v3.0.0 — variant engine
- WebSockets — real-time sync between players
- NextAuth.js — optional authentication with Google & Lichess OAuth
This platform features anonymous-first gameplay inspired by Lichess, real-time multiplayer, sound effects, and extensive testing.
- Create solo practice games or find opponents online
- Real-time move + ban synchronization with WebSockets
- Interactive chessboard powered by @bezalel6/react-chessground
- Game logic enforced by ban-chess.ts v3.0.0 with BCN (Ban Chess Notation) serialization
- Support for timed games with increment timers
- Proper ban phase mechanics - select opponent's pieces to ban their moves
- Game sound effects for moves, captures, bans, and game events
- Anonymous-first experience: Play immediately without any sign-in requirements
- Automatic guest IDs: Every visitor gets a persistent anonymous identity
- Optional authentication: Sign in with Google or Lichess OAuth if desired
- Seamless transition: Keep your games when transitioning from anonymous to authenticated
- No barriers: Following Lichess's philosophy - authentication never blocks gameplay
- Active game detection on home page with continue/resign options
- Clean resignation flow with inline split-button confirmation
- Resizable game board with persistent size preference
- Mobile-responsive design optimized for chess gameplay
- Clear game status indicators showing whose turn and what action (ban/move)
- Sound control settings with mute/volume options
- Comprehensive accessibility features
- Efficient BCN serialization for moves/bans (50% bandwidth reduction)
- Automatic game cleanup after completion (2-second archival delay)
- WebSocket connection resilience with automatic reconnection
- Redis-backed game state for persistence across server restarts
- Separated concerns: WebSocket server for live games only
- Comprehensive E2E test coverage with Playwright
- TypeScript strict mode with complete type safety
- Performance monitoring and debugging tools
2ban-2chess/
├─ app/ # Next.js 15 App Router
│ ├─ page.tsx # Landing page with active game detection
│ ├─ game/[id]/page.tsx # Dynamic game board page
│ ├─ auth/ # Authentication pages
│ │ ├─ signin/page.tsx # Sign-in page with provider options
│ │ ├─ error/page.tsx # Auth error handling
│ │ └─ logout/page.tsx # Logout page
│ ├─ play/
│ │ ├─ local/page.tsx # Solo practice mode
│ │ └─ online/page.tsx # Online matchmaking
│ ├─ settings/page.tsx # User settings and preferences
│ ├─ user/[username]/ # User profiles
│ └─ api/ # API routes
│ ├─ auth/[...nextauth]/ # NextAuth.js configuration
│ ├─ health/ # Health check endpoint
│ └─ user/username/ # Username management
│
├─ components/
│ ├─ ChessBoard.tsx # React Chessground wrapper with ban/move logic
│ ├─ GameClient.tsx # Main game UI controller
│ ├─ ActiveGameCard.tsx # Active game card with inline resign
│ ├─ AuthProvider.tsx # Authentication wrapper component
│ ├─ SoundControl.tsx # Sound settings and controls
│ ├─ auth/
│ │ ├─ SignInPanel.tsx # Sign-in options panel
│ │ └─ withAuth.tsx # Authentication HOC
│ └─ game/
│ ├─ GameSidebar.tsx # Player info & move history
│ ├─ GameStatusPanel.tsx # Game state & controls
│ ├─ ResizableBoard.tsx # Resizable chess board wrapper
│ └─ PlayerInfo.tsx # Player information display
│
├─ hooks/
│ ├─ useGameState.tsx # WebSocket game state management
│ └─ useGameTimer.tsx # Game timer functionality
│
├─ lib/
│ ├─ game-types.ts # TypeScript types & WebSocket messages
│ ├─ game-utils.ts # Game permissions & role inference
│ ├─ fen.ts # FEN parsing with ban state support
│ ├─ auth.ts # NextAuth.js configuration
│ ├─ sound-manager.ts # Game sound management
│ └─ websocket-config.ts # WebSocket connection configuration
│
├─ server/
│ ├─ ws-server.ts # WebSocket server with Redis & game cleanup
│ ├─ redis.ts # Redis connection and configuration
│ └─ services/
│ ├─ game-service.ts # Game logic service
│ └─ timer-service.ts # Timer management service
│
├─ contexts/
│ └─ WebSocketContext.tsx # WebSocket connection & auth provider
│
├─ e2e/ # Playwright E2E tests
│ ├─ auth.spec.ts # Authentication flow tests
│ ├─ game.spec.ts # Game functionality tests
│ ├─ multiplayer-flow.spec.ts # Multiplayer game tests
│ └─ accessibility.spec.ts # Accessibility tests
│
├─ types/
│ ├─ auth.ts # Authentication type definitions
│ └─ next-auth.d.ts # NextAuth.js type extensions
│
└─ docs/ # Documentation
├─ DEVELOPMENT.md # Development guide
├─ ARCHITECTURE.md # Architecture documentation
├─ DEPLOYMENT.md # Production deployment guide
├─ API_REFERENCE.md # API documentation
├─ OAUTH_SETUP.md # OAuth configuration
└─ ban-chess-api.md # BCN format specifications
git clone https://github.com/bezalel6/2ban-2chess.git
cd 2ban-2chess
npm installRecommended approach: Run each server in a separate terminal for better log insight and debugging.
Terminal 1: WebSocket Server
npm run dev:wsThis starts the WebSocket server on ws://localhost:3001 with hot reload.
Terminal 2: Next.js Development Server
npm run dev:nextThis starts the Next.js app at http://localhost:3000.
Alternative: Single Command (less optimal for debugging)
npm run devRuns both servers concurrently, but logs are mixed and harder to analyze.
📖 For detailed development setup, debugging tips, and best practices, see docs/DEVELOPMENT.md
Authentication is never required to play. If you want to enable optional OAuth sign-in, set up environment variables:
# Google OAuth (optional)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Lichess OAuth (optional)
LICHESS_CLIENT_ID=your_lichess_client_id
# NextAuth secret (required for production)
NEXTAUTH_SECRET=your_nextauth_secret
# WebSocket URL (auto-detected in development)
NEXT_PUBLIC_WEBSOCKET_URL=ws://localhost:3001📖 For detailed OAuth setup instructions, see docs/OAUTH_SETUP.md
# Run E2E tests with Playwright
npm run test
# Type checking
npm run type-check
# Linting
npm run lint
# Run both type-check and lint
npm run analyze- Visit the app: Open http://localhost:3000
- Start playing immediately: You're automatically assigned an anonymous ID
- Create/Join game:
- Solo Practice: Click "Play Local" for single-player against the engine
- Online Multiplayer: Click "Play Online" to create a game room
- Share game: Copy the URL and share with an opponent for multiplayer
- Play the game:
- Black bans first - the game starts with Black banning a White move
- If it's your turn to ban, select an opponent's piece to disable their moves
- If it's your turn to move, make a legal move on the board (cannot use banned moves)
- Turn order: Black bans → White moves → White bans → Black moves → repeat
- Game features: Real-time sync, sound effects, move history, and timer support
See RULES.md for detailed game rules, special move handling, and edge cases.
The game uses the following TypeScript types from the ban-chess.ts library:
interface Move {
from: string;
to: string;
promotion?: 'q' | 'r' | 'b' | 'n';
}
interface Ban {
from: string;
to: string;
}
type Action =
| { move: Move }
| { ban: Ban };
interface ActionResult {
success: boolean;
action?: Action;
san?: string;
error?: string;
newFen?: string;
gameOver?: boolean;
checkmate?: boolean;
stalemate?: boolean;
}
interface HistoryEntry {
turnNumber: number;
player: 'white' | 'black';
actionType: 'ban' | 'move';
action: Ban | Move;
san?: string;
fen: string;
bannedMove?: Ban;
}type ClientMsg =
| { type: "create"; gameId: string }
| { type: "join"; gameId: string }
| { type: "ban"; gameId: string; ban: Ban }
| { type: "move"; gameId: string; move: Move };type ServerMsg =
| {
type: "state";
fen: string;
pgn: string;
nextAction: "ban" | "move";
legalMoves?: Move[];
legalBans?: Ban[];
history?: HistoryEntry[];
}
| { type: "error"; message: string; error?: string };The board is rendered using react-chessground:
fen: current positionmovable.dests: built fromlegalMovesorlegalBansonMove: sends{ type: "move" }or{ type: "ban" }to server
ban-chess.tsis MITreact-chessgroundis GPL-3.0- This project is GPL-3.0 due to
react-chessgrounddependency
- ✅ Anonymous-first gameplay: Lichess-style instant play without authentication
- ✅ Real-time multiplayer: WebSocket-based gameplay
- ✅ Sound system: Game audio and sound controls
- ✅ Comprehensive testing: E2E test coverage with Playwright
- ✅ User management: Profile pages and username customization
- ✅ Mobile support: Responsive design for mobile devices
- ✅ Game persistence: Redis-backed state management
- Database persistence: Full game history storage (Postgres + Prisma)
- Matchmaking system: Automated player pairing and lobby
- Spectator mode: Watch games in progress
- Analysis board: Post-game analysis with ban history
- Rating system: ELO-based player ratings
- Tournament mode: Bracket-style competitions
For more detailed information, check out the comprehensive documentation:
- DEVELOPMENT.md - Development setup, debugging, and best practices
- ARCHITECTURE.md - Technical architecture and design decisions
- DEPLOYMENT.md - Comprehensive production deployment guide
- OAUTH_SETUP.md - OAuth provider configuration
- RULES.md - Complete Ban Chess game rules
This project includes comprehensive end-to-end testing with Playwright:
# Run all tests
npm run test
# Run specific test suites
npm run test:auth # Authentication flow tests
npm run test:game # Game functionality tests
npm run test:multiplayer # Multiplayer game tests
npm run test:a11y # Accessibility tests
# Interactive test runner
npm run test:uiTest Coverage:
- Authentication flows (OAuth + Guest)
- Solo and multiplayer gameplay
- Ban/move mechanics and validation
- Real-time WebSocket synchronization
- Accessibility compliance
- Mobile responsiveness
- ban-chess.ts by @bezalel6 - Core game engine
- @bezalel6/react-chessground - Enhanced React wrapper for Chessground
- Chessground by Lichess - Interactive chessboard library