Chess (Correspondence Chess Pro)
Correspondence chess app for two players. Originally created as “Correspondence-Chess-Pro,” the GitHub repo was renamed to “Chess” on 2026-02-12. Supports game sharing via plain-text codes (CHESS: prefix + PGN), move history with time-travel navigation, multiple board themes with dark mode, and customizable piece sets. No backend — fully client-side with localStorage persistence. Mobile-first PWA with iOS/iPad home screen install support.
Overview
Chess allows two players to conduct a correspondence game asynchronously. One player makes a move, exports a plain-text sync code, and shares it with their opponent via any messaging channel. The opponent pastes the code, views the board state, and makes their reply. No accounts, no servers, no third-party services.
The app was built with React + chess.js for complete move validation (checkmate, stalemate, en passant, castling). All game state lives client-side in localStorage.
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| TypeScript | ^5.6.0 | Primary language — strict mode enabled |
| React | ^18.2.0 | UI framework — functional components only |
| Vite | ^7.3.1 | Build tool and dev server (bumped from 5.0.8 for GHSA-67mh fix) |
| Tailwind CSS | ^3.4.1 | Utility-first CSS styling |
| chess.js | ^1.4.0 | Chess engine — FEN/PGN parsing, move validation |
| Vitest | ^2.0.0 | Unit testing framework (jsdom environment) |
| ESLint | ^9.39.2 | Code linting (flat config format) |
| Node.js | >=18.0.0 | Runtime environment |
Deployment: Static site via Vite build. Vercel-ready (vercel.json configured, auto-deploy on push). No backend required.
Architecture
src/
App.tsx # Root component — game state, move handling
components/
Board.tsx # FEN parsing, square rendering, tap-to-move input
Piece.tsx # Piece rendering with piece set selection
HistoryControls.tsx # Move history navigation (first/prev/next/last)
StatusIndicator.tsx # Game status (check, checkmate, draw)
QRCodePanel.tsx # QR code generation for game sharing (dormant)
services/
syncCode.ts # Plain-text game code encode/decode (CHESS: + PGN)
utils/
storage.ts # localStorage wrapper for game persistence
logger.ts # Console logging utility
Components/ # Legacy directory (partially migrated to src/)
State management: React hooks (useState, useMemo, useCallback) in App.tsx. chess.js Chess instance as primary game state. viewingIndex: null = current position; a number = historical position. After a 2026-03-13 refactor, App.tsx was reduced to ≤100 lines by extracting a SyncPanel component, useGameState hook, and Icons.
Game sharing: Sync codes are plain-text strings with a CHESS: prefix followed by PGN. Human-readable, copy-paste friendly, works over any channel.
Key Decisions and Patterns
- Tap-to-move over drag-and-drop — better for mobile touch targets (44px HIG compliance). See localstorage-persistence-with-zod-validation for a related client-side persistence pattern.
- CSS custom properties for board themes — runtime theme switching without React re-render, controlled via
data-board-themeHTML attribute. - IIFE in index.html for theme init — prevents flash of wrong theme on page load.
- Tailwind class-based dark mode — user-controlled toggle rather than CSS media query.
- chess.js for all move validation — no manual FEN parsing; proven library handles all rules, FEN, and PGN.
- Plain-text game codes — simplest possible sync mechanism, no encryption, human-readable.
- Module-export services (not class-based) —
syncCode.tsstructured as plain exports for tree-shaking. See module-export-services-not-class-based. - Stripped encryption — MVP testing does not need security complexity; dormant BIP-39 and idb-keyval modules inherited from original codebase remain unused.
- Vite bumped to 7.3.1 — resolved GHSA-67mh esbuild dev server vulnerability.
Current Status
Version: v1.1 shipped; v1.2 in progress Phase: v1.2 Phase 10 — Link & QR Sharing (active as of 2026-03-13) CI/CD: Passing Test coverage: 60-70% (core logic covered; App.tsx and Board.tsx have no tests) Linear Project: Aloysius Productions GitHub: irishrocker1125/Chess
v1.2 roadmap defines 3 phases and 11 requirements:
- Phase 10 — Link & QR Sharing (SHARE-01/02/03)
- Phase 11 — Multi-Game Management (GAME-01/02/03/04)
- Phase 12 — Interaction & Polish (INTX-01, UX-01/02/03/04)
Technical Debt
| Item | Priority | Notes |
|---|---|---|
| localStorage/IndexedDB dual storage | Medium | Dual backends — unclear source of truth |
| No tests for App.tsx or Board.tsx | Medium | Core game logic untested |
| Mixed directory structure (Components/ vs src/) | Low | Legacy and new structure coexist |
| Unused CCP-era utilities | Low | BIP-39, idb-keyval, QRCodePanel — dormant |
as any type cast in Board.tsx | Low | Bypasses type safety for piece types |
Related
- localstorage-persistence-with-zod-validation — client-side persistence with schema validation
- module-export-services-not-class-based — service pattern used in syncCode.ts
- single-app-component-with-usestate-hooks — App.tsx state management pattern
- dice — sibling game utility app in the iOS/web portfolio