Skip to content

πŸ—οΈ Refactor: split the 2,931-line game.js monolith into ES modulesΒ #6

Description

@llinsss

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26difficulty: hardSubstantial, multi-PR effort for experienced contributorsfrontendBrowser UI, game client, PWArefactorCode restructuring, no behavior change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions