Summary
game.js is a single 2,931-line file containing at least six unrelated concerns plus a large amount of module-level mutable state (currentAge, totalStars, playerLevel, currentLanguage, β¦ around lines 1552β1569). It's the file nearly every gameplay PR must touch, which guarantees merge conflicts and makes the code hard to test. Splitting it up is the single highest-leverage refactor for making this project contributable.
What lives in game.js today
AdaptiveLearningEngine + LearningAnalytics (difficulty adjustment, spaced repetition, session tracking) β top of file
- Accessibility settings persistence (~line 518)
- Word/curriculum data and category definitions
- Multi-language support glue (
MultiLanguageSupport, translation lookups ~lines 1622β1644, 1972, 2039)
- Speech synthesis (voice selection,
speakWord ~lines 2099β2114)
- Core game state machine, DOM manipulation, and screen navigation
- Progress persistence via scattered
localStorage calls (lines 159, 518, 1552β1561, 1703β1712, 2092β2093)
advanced-systems.js (26 KB) and ai-agent.js (26 KB) overlap with some of this and should be considered in the same pass.
Proposed structure
src/
data/words.js # curriculum/word lists (pure data)
engine/adaptive.js # AdaptiveLearningEngine
engine/analytics.js # LearningAnalytics
engine/game-state.js # score, level, stars, current word β no DOM
i18n/language.js # MultiLanguageSupport + translations
audio/speech.js # speechSynthesis wrapper
storage/persistence.js # single module owning all localStorage keys
ui/screens.js # DOM rendering & navigation
main.js # wiring
Load via <script type="module"> in game.html (no bundler needed to start; one can be added later).
Guidance for the implementer
- Do it incrementally β one module per PR is fine; extract pure-logic modules (
data, engine, storage) first since they need no DOM
- Centralizing the ~10 scattered
spellbloc_* localStorage keys behind one persistence module is the best first PR
- No behavior changes; the game must play identically after each extraction
- Pure modules (engine, data, storage) become unit-testable β add tests as they're extracted
Acceptance criteria
- No single JS file over ~500 lines for game logic
- Zero direct
localStorage calls outside the persistence module
- Game plays identically (manual test: age selection β category β word round β star award β reload page β progress retained)
Summary
game.jsis a single 2,931-line file containing at least six unrelated concerns plus a large amount of module-level mutable state (currentAge,totalStars,playerLevel,currentLanguage, β¦ around lines 1552β1569). It's the file nearly every gameplay PR must touch, which guarantees merge conflicts and makes the code hard to test. Splitting it up is the single highest-leverage refactor for making this project contributable.What lives in game.js today
AdaptiveLearningEngine+LearningAnalytics(difficulty adjustment, spaced repetition, session tracking) β top of fileMultiLanguageSupport, translation lookups ~lines 1622β1644, 1972, 2039)speakWord~lines 2099β2114)localStoragecalls (lines 159, 518, 1552β1561, 1703β1712, 2092β2093)advanced-systems.js(26 KB) andai-agent.js(26 KB) overlap with some of this and should be considered in the same pass.Proposed structure
Load via
<script type="module">ingame.html(no bundler needed to start; one can be added later).Guidance for the implementer
data,engine,storage) first since they need no DOMspellbloc_*localStorage keys behind one persistence module is the best first PRAcceptance criteria
localStoragecalls outside the persistence module