Connections Progress System — January 27, 2025
Building seamless progression: from two-puzzle isolation to a twelve-puzzle journey with smart tracking and polished completion UI.
January 27, 2025 | 8 min read
The Core Problem
This morning started with a simple player request: "Why does the game dump me back to the main menu after winning? Can't it just continue to the next puzzle?" Fair question. The original design felt abrupt—you'd finish a puzzle, celebrate briefly, then land back on the welcome screen with no sense of momentum. Time to fix that.
Connections shipped with two puzzles per difficulty level, which was fine for testing but felt thin in practice. More importantly, there was no concept of "next." Each puzzle existed in isolation. Complete one, restart from scratch. The game had no memory of your progress, no way to guide you forward. It was like reading a book where every chapter forced you to find the bookmark again.
I decided to tackle both issues at once: expand the content to three puzzles per difficulty (twelve total across Easy, Medium, Hard, Expert) and build a proper progression system that tracks which puzzles you've completed and automatically queues up the next unfinished one.
Building the Progress Tracker
The first step was adding a completedPuzzles object to the stats system:
completedPuzzles: {
easy: [], // stores completed puzzle indices
medium: [],
hard: [],
expert: [],
daily: []
}
Simple array storage—when you finish puzzle 0, it gets pushed. When you finish puzzle 2, it gets pushed. The next time you hit "Start Game," the code scans for the first missing index and loads that puzzle. If all indices are present, you've cleared the difficulty.
The tricky part was the timing. I had to mark a puzzle complete after checking win conditions but before displaying the game-over screen, otherwise the Next Puzzle button logic would read stale data. A few console logs revealed the sequence, and moving saveHighScore() to happen right after marking completion solved it cleanly.
Adding the Third Puzzle
Creating new content was straightforward but required thought. Each puzzle needs four groups of four words, with connections ranging from obvious (Easy) to subtle (Expert). I aimed for variety:
- Easy Puzzle 3: Shapes, Numbers, Furniture, Sky Objects
- Medium Puzzle 3: Metals, Flowers, Water Bodies, Capital Cities
- Hard Puzzle 3: Page Layout Terms, Programming Languages, Vocal Ranges, Gemstones
- Expert Puzzle 3: Metric Prefixes, Poetry Forms, Markup Languages, Shades of Red
The Expert categories were the most fun to design. "Latex, Markdown, HTML, XML" feels obvious once you see it, but players might confuse Markdown with a programming language or HTML with a document type. That tension—the "oh I see it now!" moment—is what makes Connections engaging.
Next Puzzle Flow
With progress tracking in place, I wired up the Next Puzzle button. The logic checks:
- Did you win this puzzle?
- Are there uncompleted puzzles in this difficulty?
If both are true, show the button. Clicking it clears the current board, increments to the next unsolved puzzle, and calls startGame() to load it. No menu detour, no friction. Just continuous flow.
The final piece was handling completion. When you finish the last puzzle in a difficulty, the game now pops a congratulations modal instead of dumping you to the menu. That modal offers two choices: upgrade to the next difficulty or return to the main menu.
Replacing System Alerts with In-Game UI
The early version used alert() and confirm() for the completion prompt. Functional, but ugly. Browser alerts break immersion and feel like error messages. I wanted something that matched the game's visual polish.
So I built a custom modal:
- A bouncing entrance animation
- An animated celebration icon (🎉 with a gentle rotation)
- Clean text hierarchy: "Congratulations!" → "You've completed all Easy puzzles!" → "Ready to challenge Medium difficulty?"
- Two styled buttons: "Try Medium" (gradient, prominent) and "Main Menu" (secondary)
The modal uses the same overlay system as the pause and game-over screens, ensuring consistent behaviour. When it appears, it also triggers three sequential fireworks bursts using the particle system—a nice touch that makes the moment feel earned.
@keyframes modalBounceIn {
0% {
opacity: 0;
transform: scale(0.7) translateY(-50px);
}
50% {
transform: scale(1.05) translateY(0);
}
100% {
opacity: 1;
transform: scale(1) translateY(0);
}
}
localStorage Drama
Everything tested fine in dev, but when I deployed and tried it live, the difficulty-complete modal appeared after finishing just the first puzzle instead of the third. Confusing. I added debug logs and realised the issue: old localStorage data from earlier testing sessions was polluting the completed arrays.
The solution was simple—add a proper reset function:
function resetProgress() {
localStorage.removeItem('connections_game_data');
location.reload();
}
Now players (and me) can wipe progress cleanly from the console if needed. More importantly, I adjusted the load logic to merge saved data carefully, ensuring the completedPuzzles structure always initialises correctly even if localStorage is partially corrupted or outdated.
Lessons from Today
1. User flow matters more than you think
The difference between "return to menu" and "continue to next puzzle" is subtle on paper, but massive in practice. One feels like work, the other feels like play.
2. Debug early, debug often
Those console.log statements saved me hours. I knew exactly when the completion check ran and what values it saw. Once the behaviour was correct, I stripped the logs out for a clean production build.
3. In-game UI beats system dialogs every time
The custom modal took 30 extra minutes to build, but the result is 10x more polished. Small details—the icon animation, the gradient button, the fireworks—add up to a cohesive experience.
4. Content expansion is deceptively hard
Adding "just one more puzzle" per difficulty sounds easy until you sit down to design twelve unique word groups that are interesting, fair, and well-balanced. I spent more time on puzzle content than on the progress code itself.
What's Next
The progression system is solid now. Next up: I'm planning to add sound effects for key moments (finishing a puzzle, unlocking the next difficulty) and maybe experiment with a "daily challenge" mode that rotates through community-submitted puzzles. But for now, the core experience is finally where I wanted it from day one—smooth, rewarding, and worth coming back to.
Can't wait to see how players respond once this build goes live.