# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## ๐ŸŽฏ IMPORTANT: Check TODO.md First! **ALWAYS check `TODO.md` for the current project tasks and priorities before making any changes.** The `TODO.md` file contains: - ๐Ÿ”ฅ Current tasks in progress - ๐Ÿ“‹ Pending features to implement - ๐Ÿšจ Known issues and blockers - โœ… Completed work for reference **Make sure to update TODO.md when:** - Starting a new task - Completing a task - Discovering new issues - Planning future improvements ## Project Overview Interactive English learning platform for children (8-9 years old) built as a modular Single Page Application. The system provides 9 different educational games that work with various content modules through a flexible architecture. ## Key Architecture Patterns ### Core System Flow 1. **AppNavigation** (`js/core/navigation.js`) - Central SPA navigation controller 2. **ContentScanner** (`js/core/content-scanner.js`) - Auto-discovers available content modules 3. **GameLoader** (`js/core/game-loader.js`) - Dynamically loads game and content modules 4. **Content Engine** (`js/core/content-engine.js`) - Processes and adapts content for games ### Module Loading System - Games and content are loaded dynamically via `GameLoader.loadGame(gameType, contentType)` - All modules register themselves on global objects: `window.GameModules` and `window.ContentModules` - Content is discovered automatically by `ContentScanner` scanning `js/content/` directory - **JSON Content Support**: New JSON-first architecture with backward compatibility to JS modules - **JSON Content Loader**: `js/core/json-content-loader.js` transforms JSON content to legacy game format - **Offline-First Loading**: Content loads from local files first, with DigitalOcean Spaces fallback - Games follow consistent constructor pattern: `new GameClass({ container, content, onScoreUpdate, onGameEnd })` ### URL-Based Navigation - Single HTML file (`index.html`) handles all navigation via URL parameters - Routes: `?page=home|games|levels|play&game=&content=` - Browser back/forward supported through `popstate` events - Navigation history maintained in `AppNavigation.navigationHistory` - Breadcrumb navigation with clickable path elements - **Top Bar**: Fixed header with app title and permanent network status indicator - **Network Status**: Real-time connectivity indicator (๐ŸŸข Online / ๐ŸŸ  Connecting / ๐Ÿ”ด Offline) - Keyboard shortcuts (ESC = go back) ## Content Module Format ### Rich Content Schema (New Architecture) Content modules support rich, multimedia educational content with optional properties. The system adapts games and exercises based on available content features: ```javascript window.ContentModules.ModuleName = { name: "Display Name", description: "Description text", difficulty: "easy|medium|hard|beginner|intermediate|advanced", language: "chinese|english|french|spanish", // Target learning language hskLevel: "HSK1|HSK2|HSK3|HSK4|HSK5|HSK6", // Chinese proficiency level // Rich vocabulary with optional multimedia vocabulary: { "word_or_character": { translation: "English translation", prononciation: "pronunciation guide", // Optional: pronunciation guide type: "noun|verb|adjective|greeting|number", // Word classification pronunciation: "audio/word.mp3", // Optional: audio file difficulty: "HSK1|HSK2|...", // Optional: individual word difficulty strokeOrder: ["stroke1", "stroke2"], // Optional: character writing order examples: ["example sentence 1"], // Optional: usage examples grammarNotes: "special usage rules" // Optional: grammar context } // OR simple format for basic content: // "word": "simple translation" }, // Grammar rules and explanations grammar: { topic_name: { title: "Grammar Rule Title", explanation: "Detailed explanation", examples: [ { chinese: "ไธญๆ–‡ไพ‹ๅญ", english: "English example", prononciation: "zhลng wรฉn lรฌ zi" } ], exercises: [/* grammar-specific exercises */] } }, // Audio content with/without text audio: { withText: [ { title: "Audio Lesson Title", audioFile: "audio/lesson1.mp3", transcript: "Full text transcript", translation: "English translation", timestamps: [{ time: 5.2, text: "specific segment" }] // Optional } ], withoutText: [ { title: "Listening Challenge", audioFile: "audio/challenge1.mp3", questions: [ { question: "What did they say?", type: "ai_interpreted" } ] } ] }, // Poetry and cultural content poems: [ { title: "Poem Title", content: "Full poem text", translation: "English translation", audioFile: "audio/poem1.mp3", // Optional culturalContext: "Historical background" } ], // Fill-in-the-blank exercises fillInBlanks: [ { sentence: "I _____ to school every day", options: ["go", "goes", "going", "went"], // Multiple choice options correctAnswer: "go", explanation: "Present tense with 'I'" }, { sentence: "The weather is _____ today", type: "open_ended", // AI-interpreted answers acceptedAnswers: ["nice", "good", "beautiful", "sunny"], aiPrompt: "Evaluate if answer describes weather positively" } ], // Sentence correction exercises corrections: [ { incorrect: "I are happy today", correct: "I am happy today", explanation: "Use 'am' with pronoun 'I'", type: "grammar_correction" } ], // Reading comprehension with AI evaluation comprehension: [ { text: "Long reading passage...", questions: [ { question: "What is the main idea?", type: "ai_interpreted", evaluationPrompt: "Check if answer captures main theme" }, { question: "Multiple choice question?", type: "multiple_choice", options: ["A", "B", "C", "D"], correctAnswer: "B" } ] } ], // Matching exercises (connect lines between columns) matching: [ { title: "Match Words to Meanings", leftColumn: ["apple", "book", "car"], rightColumn: ["่‹นๆžœ", "ไนฆ", "่ฝฆ"], correctPairs: [ { left: "apple", right: "่‹นๆžœ" }, { left: "book", right: "ไนฆ" }, { left: "car", right: "่ฝฆ" } ] } ], // Standard content (backward compatibility) sentences: [{ english: "...", chinese: "...", prononciation: "..." }], texts: [{ title: "...", content: "...", translation: "..." }], dialogues: [{ conversation: [...] }] }; ``` ### JSON Content Format (New Architecture) The platform now supports JSON content files for easier editing and maintenance: ```json { "name": "Content Name", "description": "Content description", "difficulty": "easy|medium|hard", "vocabulary": { "word": { "translation": "French translation", "prononciation": "pronunciation guide", "type": "noun|verb|adjective" } }, "sentences": [ { "english": "English sentence", "chinese": "Chinese translation", "prononciation": "pronunciation" } ], "grammar": { /* grammar rules */ }, "audio": { /* audio content */ }, "exercises": { /* exercise definitions */ } } ``` **JSON Content Loader Features:** - Automatic transformation from JSON to legacy game format - Backward compatibility with existing JavaScript content modules - Support for all rich content features (vocabulary, grammar, audio, exercises) - Offline-first loading with cloud fallback ### Content Adaptivity System The platform automatically adapts available games and exercises based on content richness: **Content Analysis:** - System scans each content module for available features - Generates compatibility scores for each game type - Recommends optimal learning activities - Handles graceful degradation when content is incomplete **Adaptive Game Selection:** - **Rich vocabulary** โ†’ Enable advanced matching games, pronunciation practice - **Audio files present** โ†’ Enable listening exercises, pronunciation challenges - **Grammar rules** โ†’ Enable correction exercises, structured lessons - **Fill-in-blanks data** โ†’ Enable cloze tests with multiple choice or AI evaluation - **Minimal content** โ†’ Fall back to basic vocabulary games **Missing Content Handling:** - Display helpful messages: "Add audio files to enable pronunciation practice" - Suggest content enrichment opportunities - Gracefully disable incompatible game modes - Provide content creation tools for missing elements **Example Adaptive Behavior:** ```javascript // Content with only basic vocabulary { vocabulary: { "hello": "ไฝ ๅฅฝ" } } โ†’ Enable: Basic matching, simple quiz โ†’ Disable: Audio practice, grammar exercises โ†’ Suggest: "Add pronunciation guide and audio for pronunciation practice" // Rich multimedia content { vocabulary: { "hello": { translation: "ไฝ ๅฅฝ", prononciation: "nว hวŽo", pronunciation: "audio/hello.mp3" } } } โ†’ Enable: All vocabulary games, audio practice, pronunciation scoring โ†’ Unlock: Advanced difficulty levels, speed challenges ``` ## ๐Ÿšจ CRITICAL ARCHITECTURE GUIDELINES **NEVER violate these principles to maintain system modularity and maintainability:** ### ๐ŸŽจ CSS Architecture Rules 1. **NEVER modify `css/games.css` for game-specific styles** - Global CSS is only for shared, reusable components - Game-specific styles MUST be injected by the game itself 2. **USE the Global CSS Base System:** ```javascript // โœ… CORRECT: Use global classes with specific overrides
// Global base class
// Global HUD structure
// Global game area
// Global answer panel // โœ… CORRECT: Inject game-specific CSS injectCSS() { const styleSheet = document.createElement('style'); styleSheet.textContent = ` .my-game-specific-element { /* Game-only styles */ } `; document.head.appendChild(styleSheet); } ``` 3. **CSS Classes Hierarchy:** - `.game-wrapper` - Base container (full screen) - `.game-wrapper.compact` - Smaller viewport variant - `.game-hud` - Top information bar - `.game-area` - Main play zone - `.answer-panel` - Bottom interaction zone - `.answer-btn` - Interactive buttons 4. **โŒ FORBIDDEN PATTERNS:** ```css /* โŒ NEVER add game-specific classes to games.css */ .word-storm-wrapper { } .my-game-specific-class { } /* โŒ NEVER hardcode game-specific dimensions in global CSS */ .game-area { height: 600px; } /* This breaks other games */ ``` ### ๐ŸŽฎ Game Development Standards 1. **Self-Contained Games:** - Each game MUST inject its own CSS via `injectCSS()` - Games MUST use global base classes where possible - Game-specific elements get their own CSS only 2. **Constructor Pattern (REQUIRED):** ```javascript class MyGame { constructor({ container, content, onScoreUpdate, onGameEnd }) { this.injectCSS(); // Inject game-specific styles this.init(); // Setup interface } start() { /* Start game logic */ } destroy() { /* Cleanup */ } } ``` 3. **Module Registration (REQUIRED):** ```javascript // MUST be at end of game file window.GameModules = window.GameModules || {}; window.GameModules.MyGame = MyGame; ``` 4. **GameLoader Integration:** - Add game mapping in `game-loader.js` โ†’ `getModuleName()` - Add compatibility rules in `content-game-compatibility.js` - Add game config in `navigation.js` โ†’ game configuration ### ๐Ÿ”ง Modification Guidelines **When adding new games:** 1. โœ… Use existing global CSS classes 2. โœ… Inject only game-specific CSS 3. โœ… Follow constructor pattern 4. โœ… Add to GameLoader mapping **When modifying existing games:** 1. โœ… Keep changes within the game file 2. โœ… Don't break global CSS compatibility 3. โœ… Test with multiple content types **When adding global features:** 1. โœ… Add to global CSS base classes 2. โœ… Ensure backward compatibility 3. โœ… Update this documentation ### ๐Ÿš€ Benefits of This Architecture - **Modularity**: Each game is self-contained - **Reusability**: Base classes work for all games - **Maintainability**: Changes don't break other games - **Performance**: Only load CSS when game is used - **Scalability**: Easy to add new games ### โš ๏ธ Common Mistakes to Avoid **CSS Architecture Violations:** ```css /* โŒ DON'T: Adding game-specific styles to games.css */ .word-storm-wrapper { height: 80vh; width: 90vw; } /* โœ… DO: Use global classes with game-specific injection */ // In game file: injectCSS() { // Game-specific overrides only styleSheet.textContent = `.falling-word { animation: wordGlow 2s; }`; } ``` **Module Loading Issues:** ```javascript // โŒ DON'T: Forget GameLoader mapping // Game won't load because getModuleName() doesn't know about it // โœ… DO: Add to game-loader.js const names = { 'my-game': 'MyGame' // Add this mapping }; ``` **HTML Structure Violations:** ```html
``` **Integration Checklist:** - [ ] Game CSS injected via `injectCSS()` - [ ] Global classes used for structure - [ ] GameLoader mapping added - [ ] Compatibility rules defined - [ ] Constructor pattern followed - [ ] Module registration at file end ## Game Module Format Game modules must export to `window.GameModules` with this pattern: ```javascript class GameName { constructor({ container, content, onScoreUpdate, onGameEnd }) { this.container = container; this.content = content; this.onScoreUpdate = onScoreUpdate; this.onGameEnd = onGameEnd; } start() { /* Initialize game */ } destroy() { /* Cleanup */ } restart() { /* Reset game state */ } } window.GameModules = window.GameModules || {}; window.GameModules.GameName = GameName; ``` ## Configuration System - **Main config**: `config/games-config.json` - defines available games and content - **Environment config**: `js/core/env-config.js` - DigitalOcean Spaces configuration and offline settings - **Content discovery**: Automatic scanning of both `.js` and `.json` content files - Games can be enabled/disabled via `games.{gameType}.enabled` - **Cloud Integration**: DigitalOcean Spaces endpoint configuration for remote content - **Offline-First Strategy**: Local content prioritized, remote fallback with timeout protection - UI settings, scoring rules, and feature flags also in main config ## Development Workflow ### Running the Application Open `index.html` in a web browser - no build process required. All modules load dynamically. ### Adding New Games 1. Create `js/games/{game-name}.js` with proper module export 2. Add game configuration to `config/games-config.json` 3. Update `AppNavigation.getDefaultConfig()` if needed ### Adding New Content **Option 1: JSON Format (Recommended)** 1. Create `js/content/{content-name}.json` with proper JSON structure 2. Content will be auto-discovered and loaded via JSON Content Loader 3. Easier to edit and maintain than JavaScript files **Option 2: JavaScript Format (Legacy)** 1. Create `js/content/{content-name}.js` with proper module export 2. Add filename to `ContentScanner.contentFiles` array 3. Content will be auto-discovered on next app load ### Content Creation Tool - Built-in content creator at `js/tools/content-creator.js` - Accessible via "Crรฉateur de Contenu" button on home page - Generates properly formatted content modules ## Key Files by Function **Navigation & Loading:** - `js/core/navigation.js` - SPA navigation controller (452 lines) - `js/core/game-loader.js` - Dynamic module loading (336 lines) - `js/core/content-scanner.js` - Auto content discovery (376 lines) **Content Processing:** - `js/core/content-engine.js` - Content processing engine (484 lines) - `js/core/content-factory.js` - Exercise generation (553 lines) - `js/core/content-parsers.js` - Content parsing utilities (484 lines) - `js/core/json-content-loader.js` - JSON to legacy format transformation - `js/core/env-config.js` - Environment and cloud configuration **Game Implementations:** - `js/games/whack-a-mole.js` - Standard version (623 lines) - `js/games/whack-a-mole-hard.js` - Difficult version (643 lines) - `js/games/memory-match.js` - Memory pairs game (403 lines) - `js/games/quiz-game.js` - Quiz system (354 lines) - `js/games/fill-the-blank.js` - Sentence completion (418 lines) - `js/games/text-reader.js` - Guided text reading (366 lines) - `js/games/adventure-reader.js` - RPG-style adventure (949 lines) ## Important Implementation Details ### Scoring System - Games call `this.onScoreUpdate(score)` to update display - Final scores saved to localStorage with key pattern: `score_{gameType}_{contentType}` - Best scores tracked and displayed in game-end modal - Points per correct answer, malus per error, speed bonus - Score history and achievement badges ### Content Compatibility - `ContentScanner` evaluates content compatibility with each game type - Compatibility scoring helps recommend best content for each game - Games should handle various content formats gracefully ### Memory Management - `GameLoader.cleanup()` called before loading new games - Games should implement `destroy()` method for proper cleanup - Previous game instances must be cleaned up to prevent memory leaks ### Error Handling - Content loading errors logged but don't crash the application - Fallback mechanisms for missing content or games - User-friendly error messages via `Utils.showToast()` ## Design Guidelines ### Visual Design Principles - Modern, clean design optimized for children (8-9 years old) - Large, tactile buttons (minimum 44px for touch interfaces) - High contrast colors for accessibility - Smooth, non-aggressive animations - Emoji icons combined with text labels ### Color Palette - **Primary**: Blue (#3B82F6) - Trust, learning - **Secondary**: Green (#10B981) - Success, validation - **Accent**: Orange (#F59E0B) - Energy, attention - **Error**: Red (#EF4444) - Clear error indication - **Neutral**: Gray (#6B7280) - Text, backgrounds ### Accessibility Features - Full keyboard navigation support - Alternative text for all images - Adjustable font sizes - High contrast mode compatibility - Screen reader friendly markup ### Responsive Design - Mobile/tablet adaptation - Touch-friendly interface - Portrait/landscape orientation support - Fluid layouts that work on various screen sizes - **Fixed Top Bar**: App title and network status always visible - **Network Status**: Automatic hiding of status text on mobile devices - **Content Margin**: Proper spacing to accommodate fixed header ## Git Configuration ### Repository - **Remote**: Bitbucket repository at `AlexisTrouve/class-generator-system` - **Port 443 Configuration**: Git is configured to use SSH over port 443 for network restrictions - **Remote URL**: `ssh://git@altssh.bitbucket.org:443/AlexisTrouve/class-generator-system.git` ### SSH Configuration To push to the repository through port 443, the following SSH configuration is required in `~/.ssh/config`: ``` Host altssh.bitbucket.org HostName altssh.bitbucket.org Port 443 User git IdentityFile ~/.ssh/bitbucket_key ``` ### Push Commands - Standard push: `git push` - Set upstream: `git push --set-upstream origin master` ## ๐Ÿšจ **Developer Guidelines & Common Pitfalls** **Critical information for future developers to avoid common mistakes and maintain code quality.** ### **๐Ÿ”ฅ Template Literals Syntax Errors** **MOST COMMON BUG - Always check this first:** ```javascript // โŒ FATAL ERROR - Will break entire module styleSheet.textContent = \`css here\`; // Backslash = SyntaxError // โœ… CORRECT styleSheet.textContent = `css here`; // Backtick (grave accent) ``` **How to debug:** ```bash # Test syntax before browser testing node -c js/games/your-game.js # Look for "Invalid or unexpected token" errors # Usually points to template literal issues ``` ### **๐ŸŽฎ Game Development Best Practices** #### **Required Game Structure:** ```javascript class NewGame { constructor({ container, content, onScoreUpdate, onGameEnd }) { this.injectCSS(); // CSS injection FIRST this.extractContent(); // Content processing this.init(); // UI initialization } start() { // Separate start method - NOT in constructor this.startGameLogic(); } destroy() { // Cleanup intervals, event listeners, injected CSS this.cleanup(); } } // REQUIRED: Global module registration window.GameModules = window.GameModules || {}; window.GameModules.NewGame = NewGame; ``` #### **CSS Architecture - Zero Tolerance Policy:** ```javascript // โœ… CORRECT: Inject game-specific CSS injectCSS() { if (document.getElementById('my-game-styles')) return; // Prevent duplicates const styleSheet = document.createElement('style'); styleSheet.id = 'my-game-styles'; styleSheet.textContent = ` .my-game-element { color: red; } .falling-word { animation: myCustomAnimation 2s; } `; document.head.appendChild(styleSheet); } // โŒ FORBIDDEN: Modifying css/games.css for game-specific styles // css/games.css should ONLY contain global reusable classes ``` ### **๐Ÿ” Debug Templates for Quick Testing** #### **Isolated Game Testing:** ```html
``` ### **๐ŸŒ Interface Language Standards** **All UI text must be in English:** ```javascript // โœ… CORRECT "Score: ${score}" "Lives: ${lives}" "Level Up!" "Game Over" "Back to Games" // โŒ FORBIDDEN "Score: ${score} points" // French "Vies: ${lives}" // French "Niveau supรฉrieur!" // French ``` ### **๐Ÿ“‹ Integration Checklist** **Before committing any new game:** - [ ] โœ… Syntax check: `node -c js/games/your-game.js` - [ ] โœ… CSS injected via `injectCSS()` method - [ ] โœ… No modifications to `css/games.css` - [ ] โœ… Uses global classes: `.game-wrapper`, `.game-hud`, `.game-area`, `.answer-panel` - [ ] โœ… GameLoader mapping added in `getModuleName()` - [ ] โœ… Navigation config updated in `navigation.js` - [ ] โœ… Constructor pattern followed exactly - [ ] โœ… Module export at end of file - [ ] โœ… English-only interface text - [ ] โœ… Isolated test file created and working ### **โšก Performance & Architecture Notes** **Current System Architecture:** - **CSS:** Global base classes + per-game injection - **Content:** Auto-discovery + JSON/JS dual support - **Navigation:** URL-based SPA with dynamic loading - **Modules:** Dynamic import + backward compatibility **Critical Files (DO NOT BREAK):** - `js/core/game-loader.js` - Module name mapping - `css/games.css` - Global CSS base (game-agnostic only) - `js/core/navigation.js` - Game configuration and routing ### **๐Ÿ”ง Common Debugging Commands** ```bash # Check file syntax node -c js/games/your-game.js # Check for non-ASCII characters (encoding issues) grep -P '[^\x00-\x7F]' js/games/your-game.js # Find template literal issues grep -n "\\\`" js/games/your-game.js # Test local server python3 -m http.server 8000 # Then: http://localhost:8000/?page=play&game=your-game&content=available-content ``` ### **๐Ÿš€ Quick Win Tips** 1. **Copy working game structure** - Use existing games as templates 2. **Test isolated first** - Don't debug through the full app initially 3. **Check browser console** - JavaScript errors are usually obvious 4. **Verify content compatibility** - Make sure your content has the data your game needs 5. **Use global CSS classes** - Don't reinvent layout, build on existing structure **Remember: Most bugs are simple syntax errors (especially template literals) or missing module registrations. Check these first!** ๐ŸŽฏ ## ๐Ÿค **Collaborative Development Best Practices** **Critical lesson learned from real debugging sessions:** ### **โœ… Always Test Before Committing** **โŒ BAD WORKFLOW:** 1. Write code 2. Immediately commit 3. Discover it doesn't work 4. Debug on committed broken code **โœ… GOOD WORKFLOW:** 1. Write code 2. **TEST THOROUGHLY** 3. If broken โ†’ debug cooperatively 4. When working โ†’ commit ### **๐Ÿ” Cooperative Debugging Method** **When user reports: "รงa marche pas" or "y'a pas de lettres":** 1. **Get specific symptoms** - Don't assume, ask exactly what they see 2. **Add targeted debug logs** - Console.log the exact variables in question 3. **Test together** - Have user run and report console output 4. **Analyze together** - Look at debug output to find root cause 5. **Fix precisely** - Target the exact issue, don't rewrite everything **Real Example - Letter Discovery Issue:** ```javascript // โŒ ASSUMPTION: "Letters not working, must rewrite everything" // โœ… ACTUAL DEBUG: console.log('๐Ÿ” DEBUG this.content.letters:', this.content.letters); // undefined console.log('๐Ÿ” DEBUG this.content.rawContent?.letters:', this.content.rawContent?.letters); // {U: Array(4), V: Array(4), T: Array(4)} // โœ… PRECISE FIX: Check both locations const letters = this.content.letters || this.content.rawContent?.letters; ``` ### **๐ŸŽฏ Key Principles** - **Communication > Code** - Clear problem description saves hours - **Debug logs > Assumptions** - Add console.log to see actual data - **Test early, test often** - Don't tunnel vision on untested code - **Pair debugging** - Two brains spot issues faster than one - **Patience > Speed** - Taking time to understand beats rushing broken fixes **"C'est mieux quand on prend notre temps en coop plutot que de tunnel vision !"** ๐ŸŽฏ