Restructured project from nested workspace pattern to flat single-repo layout. This eliminates redundant nesting and consolidates all project files under version control. ## Migration Summary **Before:** ``` alex/ (workspace, not versioned) ├── chess-game/ (git repo) │ ├── js/, css/, tests/ │ └── index.html └── docs/ (planning, not versioned) ``` **After:** ``` alex/ (git repo, everything versioned) ├── js/, css/, tests/ ├── index.html ├── docs/ (project documentation) ├── planning/ (historical planning docs) ├── .gitea/ (CI/CD) └── CLAUDE.md (configuration) ``` ## Changes Made ### Structure Consolidation - Moved all chess-game/ contents to root level - Removed redundant chess-game/ subdirectory - Flattened directory structure (eliminated one nesting level) ### Documentation Organization - Moved chess-game/docs/ → docs/ (project documentation) - Moved alex/docs/ → planning/ (historical planning documents) - Added CLAUDE.md (workspace configuration) - Added IMPLEMENTATION_PROMPT.md (original project prompt) ### Version Control Improvements - All project files now under version control - Planning documents preserved in planning/ folder - Merged .gitignore files (workspace + project) - Added .claude/ agent configurations ### File Updates - Updated .gitignore to include both workspace and project excludes - Moved README.md to root level - All import paths remain functional (relative paths unchanged) ## Benefits ✅ **Simpler Structure** - One level of nesting removed ✅ **Complete Versioning** - All documentation now in git ✅ **Standard Layout** - Matches open-source project conventions ✅ **Easier Navigation** - Direct access to all project files ✅ **CI/CD Compatible** - All workflows still functional ## Technical Validation - ✅ Node.js environment verified - ✅ Dependencies installed successfully - ✅ Dev server starts and responds - ✅ All core files present and accessible - ✅ Git repository functional ## Files Preserved **Implementation Files:** - js/ (3,517 lines of code) - css/ (4 stylesheets) - tests/ (87 test cases) - index.html - package.json **CI/CD Pipeline:** - .gitea/workflows/ci.yml - .gitea/workflows/release.yml **Documentation:** - docs/ (12+ documentation files) - planning/ (historical planning materials) - README.md **Configuration:** - jest.config.js, babel.config.cjs, playwright.config.js - .gitignore (merged) - CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
20 KiB
Developer Guide - HTML Chess Game
Table of Contents
- Development Environment
- Project Structure
- Development Workflow
- Testing Strategy
- Debugging Guide
- Performance Optimization
- Code Style Guide
- Deployment
- Troubleshooting
Development Environment
Prerequisites
Required:
- Modern web browser (Chrome 60+, Firefox 54+, Safari 10.1+, Edge 79+)
- Text editor or IDE (VS Code recommended)
- Git for version control
Optional:
- Node.js (for local server and testing)
- Browser dev tools extensions
- Code formatters (Prettier recommended)
Initial Setup
1. Clone or Create Project
# Create new project
mkdir chess-game
cd chess-game
# Initialize git (optional)
git init
# Create project structure
mkdir -p {css,js/{game,pieces,moves,ui,utils},assets/pieces,tests/{unit,integration},docs}
2. Install Development Tools (Optional)
# Initialize npm (for testing framework)
npm init -y
# Install dev dependencies (optional)
npm install --save-dev \
live-server \
eslint \
prettier \
jest
3. Set Up Live Server
Option 1: Using Python
python3 -m http.server 8000
Option 2: Using Node.js
npx http-server -p 8000
Option 3: Using VS Code Extension
- Install "Live Server" extension
- Right-click
index.html→ "Open with Live Server"
4. Configure Editor
VS Code Settings (.vscode/settings.json):
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"javascript.preferences.quoteStyle": "single",
"files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true
}
ESLint Config (.eslintrc.json):
{
"env": {
"browser": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"indent": ["error", 4],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
}
Prettier Config (.prettierrc):
{
"singleQuote": true,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"trailingComma": "es5"
}
Project Structure
Directory Organization
chess-game/
├── index.html # Main entry point
├── package.json # npm configuration (optional)
├── .gitignore # Git ignore rules
├── .eslintrc.json # ESLint configuration
├── .prettierrc # Prettier configuration
│
├── css/ # Stylesheets
│ ├── board.css # Chess board styling
│ ├── pieces.css # Piece styling
│ └── ui.css # UI components
│
├── js/ # JavaScript modules
│ ├── main.js # Application entry point
│ │
│ ├── game/ # Game logic
│ │ ├── ChessGame.js # Main game controller
│ │ ├── Board.js # Board state management
│ │ └── GameState.js # Game state and history
│ │
│ ├── pieces/ # Piece implementations
│ │ ├── Piece.js # Base piece class
│ │ ├── Pawn.js # Pawn logic
│ │ ├── Knight.js # Knight logic
│ │ ├── Bishop.js # Bishop logic
│ │ ├── Rook.js # Rook logic
│ │ ├── Queen.js # Queen logic
│ │ └── King.js # King logic
│ │
│ ├── moves/ # Move validation
│ │ ├── MoveValidator.js # Move validation
│ │ ├── MoveGenerator.js # Legal move generation
│ │ └── SpecialMoves.js # Special moves
│ │
│ ├── ui/ # UI components
│ │ ├── BoardRenderer.js # Board rendering
│ │ ├── DragDropHandler.js # Drag-and-drop
│ │ └── UIController.js # UI state management
│ │
│ └── utils/ # Utilities
│ ├── notation.js # Chess notation
│ ├── storage.js # localStorage wrapper
│ └── helpers.js # Helper functions
│
├── assets/ # Static assets
│ └── pieces/ # Piece images (SVG)
│ ├── white-king.svg
│ ├── white-queen.svg
│ └── ...
│
├── tests/ # Test files
│ ├── unit/ # Unit tests
│ │ ├── Board.test.js
│ │ ├── pieces/
│ │ └── moves/
│ │
│ └── integration/ # Integration tests
│ └── gameplay.test.js
│
└── docs/ # Documentation
├── README.md
├── IMPLEMENTATION_GUIDE.md
├── API_REFERENCE.md
└── ...
Module Dependencies
main.js
├── ChessGame.js
│ ├── Board.js
│ ├── GameState.js
│ └── MoveValidator.js
│ ├── Piece.js (and subclasses)
│ └── SpecialMoves.js
│
└── UIController.js
├── BoardRenderer.js
└── DragDropHandler.js
Utilities (used everywhere):
├── notation.js
├── storage.js
└── helpers.js
Development Workflow
1. Feature Development Cycle
# 1. Create feature branch (if using git)
git checkout -b feature/castling-logic
# 2. Write failing test first (TDD)
# Edit tests/unit/moves/SpecialMoves.test.js
# 3. Run tests
npm test
# 4. Implement feature
# Edit js/moves/SpecialMoves.js
# 5. Run tests until passing
npm test
# 6. Refactor if needed
# Clean up code, improve performance
# 7. Commit changes
git add .
git commit -m "feat: implement castling logic"
# 8. Merge to main
git checkout main
git merge feature/castling-logic
2. Daily Development Routine
Morning:
- Pull latest changes
- Review open issues
- Plan tasks for the day
- Set up development environment
During Development:
- Write test first (TDD)
- Implement minimal code to pass
- Refactor for quality
- Commit frequently
- Run full test suite periodically
End of Day:
- Run full test suite
- Commit all changes
- Push to repository
- Update task tracker
- Document any blockers
3. Code Review Process
Before Requesting Review:
- All tests passing
- Code formatted and linted
- No console errors
- Documentation updated
- Self-review completed
Review Checklist:
- Code follows style guide
- Tests are comprehensive
- No performance regressions
- Edge cases handled
- Documentation accurate
Testing Strategy
Unit Testing
Framework: Jest (or your choice)
Test Structure:
// tests/unit/pieces/Rook.test.js
import { Rook } from '../../../js/pieces/Rook.js';
import { Board } from '../../../js/game/Board.js';
describe('Rook', () => {
let board;
beforeEach(() => {
board = new Board();
board.clear(); // Start with empty board
});
describe('getValidMoves', () => {
it('should move vertically', () => {
const rook = new Rook('white', {row: 4, col: 4});
board.setPiece(4, 4, rook);
const moves = rook.getValidMoves(board);
const verticalMoves = moves.filter(m => m.col === 4);
expect(verticalMoves.length).toBe(7);
});
it('should be blocked by friendly pieces', () => {
const rook = new Rook('white', {row: 4, col: 4});
const blockingPawn = new Pawn('white', {row: 4, col: 6});
board.setPiece(4, 4, rook);
board.setPiece(4, 6, blockingPawn);
const moves = rook.getValidMoves(board);
const rightMoves = moves.filter(m => m.row === 4 && m.col > 4);
expect(rightMoves.length).toBe(1); // Only to col 5
});
it('should capture enemy pieces', () => {
const rook = new Rook('white', {row: 4, col: 4});
const enemyPawn = new Pawn('black', {row: 4, col: 6});
board.setPiece(4, 4, rook);
board.setPiece(4, 6, enemyPawn);
const moves = rook.getValidMoves(board);
const canCaptureEnemy = moves.some(m =>
m.row === 4 && m.col === 6
);
expect(canCaptureEnemy).toBe(true);
});
});
});
Run Tests:
# Run all tests
npm test
# Run specific file
npm test -- Rook.test.js
# Run with coverage
npm test -- --coverage
# Watch mode
npm test -- --watch
Integration Testing
Test Complete Scenarios:
// tests/integration/gameplay.test.js
describe('Complete Game Scenarios', () => {
it('should handle Scholar\'s Mate', () => {
const game = new ChessGame();
// Move sequence
expect(game.makeMove(6, 4, 4, 4).success).toBe(true); // e4
expect(game.makeMove(1, 4, 3, 4).success).toBe(true); // e5
expect(game.makeMove(7, 5, 4, 2).success).toBe(true); // Bc4
expect(game.makeMove(1, 1, 2, 2).success).toBe(true); // Nc6
expect(game.makeMove(7, 3, 3, 7).success).toBe(true); // Qh5
expect(game.makeMove(1, 6, 2, 5).success).toBe(true); // Nf6
expect(game.makeMove(3, 7, 1, 5).success).toBe(true); // Qxf7#
// Verify checkmate
expect(game.status).toBe('checkmate');
expect(game.winner).toBe('white');
});
it('should handle stalemate', () => {
const game = new ChessGame();
// Set up stalemate position
game.board.fromFEN('7k/5Q2/6K1/8/8/8/8/8 b - - 0 1');
expect(game.isStalemate('black')).toBe(true);
expect(game.status).toBe('stalemate');
});
});
Manual Testing Checklist
Before Each Release:
- All piece types move correctly
- Special moves work (castling, en passant, promotion)
- Check detection accurate
- Checkmate detection accurate
- Stalemate detection accurate
- UI responsive and intuitive
- Save/load functionality works
- Undo/redo works correctly
- No console errors
- Performance acceptable
- Works in all target browsers
Debugging Guide
Browser Developer Tools
Console Debugging:
// Add debug logging
console.log('Move validation:', {
piece: piece.type,
from: {row: fromRow, col: fromCol},
to: {row: toRow, col: toCol},
valid: result
});
// Use debugger statement
function makeMove(fromRow, fromCol, toRow, toCol) {
debugger; // Execution will pause here
const piece = this.board.getPiece(fromRow, fromCol);
// ...
}
// Group related logs
console.group('Move Validation');
console.log('Piece:', piece);
console.log('Valid moves:', validMoves);
console.log('Target:', {toRow, toCol});
console.groupEnd();
Breakpoints:
- Open DevTools (F12)
- Go to Sources tab
- Find your file
- Click line number to set breakpoint
- Refresh page to trigger
Watch Expressions:
- Add
this.board.gridto watch - Add
this.gameState.moveHistoryto watch - Add
this.currentTurnto watch
Common Issues and Solutions
Issue: Infinite Recursion in Check Detection
Problem:
// Bad: Causes infinite loop
function isMoveLegal(board, piece, toRow, toCol) {
const validMoves = piece.getValidMoves(board); // Calls isMoveLegal again!
// ...
}
Solution:
// Good: Separate concerns
function getValidMoves(board, piece) {
// Get moves without check validation
}
function getLegalMoves(board, piece) {
// Filter valid moves by check constraint
return getValidMoves(board, piece)
.filter(move => !leavesKingInCheck(board, piece, move));
}
Issue: Drag and Drop Not Working
Checklist:
- Element has
draggable="true" - Event listeners attached to correct elements
dataTransferused correctlypreventDefault()called indragover
Debug:
boardElement.addEventListener('dragstart', (e) => {
console.log('Drag started:', e.target);
console.log('Data:', e.dataTransfer.getData('text/plain'));
});
boardElement.addEventListener('dragover', (e) => {
console.log('Drag over:', e.target);
e.preventDefault(); // Don't forget this!
});
Issue: Pieces Not Rendering
Checklist:
- CSS classes applied correctly
- Grid layout configured
- Z-index issues
- Unicode symbols or images loading
Debug:
// Verify DOM structure
console.log('Board HTML:', boardElement.innerHTML);
console.log('Squares:', boardElement.querySelectorAll('.square').length);
console.log('Pieces:', boardElement.querySelectorAll('.piece').length);
Performance Profiling
Using Chrome DevTools:
- Open DevTools → Performance tab
- Click Record
- Perform action (e.g., make move)
- Stop recording
- Analyze timeline
Identify Bottlenecks:
- Excessive DOM manipulation
- Slow move validation
- Memory leaks
- Unnecessary re-renders
Solution:
// Before: Slow
function updateBoard() {
boardElement.innerHTML = ''; // Triggers reflow
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
// Create and append elements
}
}
}
// After: Fast
function updateBoard() {
const fragment = document.createDocumentFragment();
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
// Create elements and append to fragment
}
}
boardElement.innerHTML = '';
boardElement.appendChild(fragment); // Single reflow
}
Performance Optimization
Minimize DOM Manipulation
Use Document Fragments:
const fragment = document.createDocumentFragment();
// Add all elements to fragment
container.appendChild(fragment); // Single DOM update
Batch Updates:
// Bad: Multiple reflows
element.style.width = '100px';
element.style.height = '100px';
element.style.backgroundColor = 'red';
// Good: Single reflow
element.style.cssText = 'width: 100px; height: 100px; background-color: red;';
Memoize Expensive Calculations
class Piece {
constructor() {
this._validMovesCache = null;
this._cacheValidUntil = null;
}
getValidMoves(board) {
const boardHash = board.getHash();
if (this._cacheValidUntil === boardHash) {
return this._validMovesCache;
}
// Calculate moves
this._validMovesCache = this.calculateValidMoves(board);
this._cacheValidUntil = boardHash;
return this._validMovesCache;
}
invalidateCache() {
this._validMovesCache = null;
this._cacheValidUntil = null;
}
}
Debounce UI Updates
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Usage
const updateUI = debounce(() => {
renderer.renderBoard(game.board, game.gameState);
}, 100);
Optimize Event Handlers
Use Event Delegation:
// Bad: Many listeners
squares.forEach(square => {
square.addEventListener('click', handleClick);
});
// Good: Single listener
boardElement.addEventListener('click', (e) => {
const square = e.target.closest('.square');
if (square) {
handleClick(square);
}
});
Code Style Guide
Naming Conventions
Variables:
// camelCase for variables and functions
const currentTurn = 'white';
const isKingInCheck = true;
function makeMove(from, to) { }
Classes:
// PascalCase for classes
class ChessGame { }
class MoveValidator { }
Constants:
// UPPER_SNAKE_CASE for constants
const MAX_MOVES = 500;
const DEFAULT_FEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';
Private Members:
// Prefix with underscore
class Piece {
constructor() {
this._cachedMoves = null;
}
}
File Organization
One class per file:
// Good: Rook.js
export class Rook extends Piece {
// ...
}
// Bad: pieces.js with all pieces
export class Rook { }
export class Bishop { }
export class Knight { }
Related functions can be grouped:
// utils/helpers.js
export function clamp(value, min, max) { }
export function isInBounds(row, col) { }
export function getOppositeColor(color) { }
Documentation
JSDoc Comments:
/**
* Validates if a move is legal according to chess rules
*
* @param {Board} board - The current board state
* @param {Piece} piece - The piece to move
* @param {number} toRow - Target row (0-7)
* @param {number} toCol - Target column (0-7)
* @param {GameState} gameState - Current game state
* @returns {boolean} True if move is legal
*/
static isMoveLegal(board, piece, toRow, toCol, gameState) {
// ...
}
Error Handling
Use descriptive errors:
// Good
if (!piece) {
throw new Error(`No piece found at position (${row}, ${col})`);
}
// Bad
if (!piece) {
throw new Error('Invalid');
}
Return result objects:
function makeMove(from, to) {
if (!isValid) {
return {
success: false,
error: 'Invalid move: piece cannot move there'
};
}
return {
success: true,
move: executedMove
};
}
Deployment
Pre-Deployment Checklist
- All tests passing
- No console errors
- Code minified (optional)
- Assets optimized
- Browser compatibility tested
- Performance acceptable
- Documentation updated
Build Process (Optional)
If using build tools:
# Install build tools
npm install --save-dev webpack webpack-cli
# Create webpack.config.js
# Build for production
npm run build
Static Hosting
GitHub Pages:
# Create gh-pages branch
git checkout -b gh-pages
# Push to GitHub
git push origin gh-pages
# Access at: https://username.github.io/chess-game
Netlify:
- Connect GitHub repository
- Set build command (if any)
- Set publish directory
- Deploy
Vercel:
npm install -g vercel
vercel deploy
Performance Optimization for Production
Minify CSS/JS:
# CSS
npx cssnano css/board.css > dist/board.min.css
# JS
npx terser js/main.js -o dist/main.min.js
Optimize Images:
- Use SVG for piece images (scalable)
- Compress PNG/JPG if used
- Use appropriate formats
Enable Compression:
# .htaccess for Apache
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript
</IfModule>
Troubleshooting
Common Errors
"Uncaught TypeError: Cannot read property 'grid' of undefined"
- Board not initialized
- Check constructor calls
- Verify import statements
"Maximum call stack size exceeded"
- Infinite recursion
- Check move validation logic
- Verify event listener cleanup
Drag and drop not working
- Check draggable attribute
- Verify event listeners
- Call preventDefault() in dragover
Getting Help
- Check documentation
- Review API reference
- Search existing issues
- Ask specific questions with code samples
Next: See HANDOFF_CHECKLIST.md for implementation timeline