I built the accessibility feature first and the game around it, which is backwards, and I would do it that way again.
What It Is
Drop animal-shaped blocks onto an 8x8 grid. Fill a row or a column and it clears. You get three minutes, and the only way to get more time is to keep clearing. When nothing in your tray fits anywhere, the run is over.
A React module inside the Wanessa Labs Games Hub. One puzzle a day, the same for everyone. No accounts, no backend, no network calls, no images during play. The twelve animals are SVG shapes drawn in the repo, so there is nothing to load and nothing to license.
Every Colour Game Fails the Same Way
The genre this comes from, 1010! and Block Blast, tells you what a piece is by colouring it. If you cannot separate those colours, you are playing a harder game than everyone else, and nobody tells you that.
So each shape here has a fixed animal and a fixed colour, and all three say the same thing. A 1x3 is a snake, is green, always. You can play by shape, by silhouette, or by colour, and any one of the three is enough.
That still leaves a problem. Twelve animals want twelve colours, and twelve reliably distinguishable colours do not exist, particularly not for colourblind players. So there are seven, shared between animals whose shapes could never be confused: the 1x3 snake and the L-shaped frog take the same green, and they are different sizes and different geometries.
The seven are chosen so they separate on lightness alone, from 0.36 to 0.68, with a real gap between each. With no colour vision at all the board is still a legible staircase from dark to light. A test checks that ladder in every theme the hub has, so if someone later nudges a colour and two roles collapse into each other, the build fails instead of the game quietly getting worse.
One more thing fell out of this. The animal shape repeats in every cell of a piece rather than stretching across it. A single stretched eel across five squares looks better in the tray and then disappears the moment you place it, and a cleared line would carry no animal information at all. Eight identical frogs in a row is unmistakable, and it is what makes the bonus for clearing a single-animal line visible to someone who cannot see that it is green.
The Clock Is the Whole Design
Three minutes, counting down. Clearing a line gives you three seconds back. Clearing several at once gives you more, five, then seven, then nine.
But the clock cannot go past three minutes. Ever. Every second you win is a second you already spent, so you are never getting ahead, only falling behind more slowly. That ceiling is what the game is actually about.
Unless you catch the Golden Critter. One piece each day is marked, planted at a fixed position in the day’s sequence, the same position for everyone. Clear a line containing it and the ceiling comes off for the rest of that run and boosts start actually accumulating. Miss it and you play the whole run under the cap.
The Best Mechanic Was Unreachable and Reading the Code Would Never Have Shown It
The Golden Critter was planted somewhere between the 9th and 89th piece of the day.
That looked fine. I wrote it, it was seeded, it was fair, everyone got the same one. Then I built a scripted player that always takes the first legal spot, ran it across forty days, and counted.
It died around the 23rd piece. And even generously, three minutes is about ninety pieces for someone who is fast and never hesitates. So the 89th piece was not “deep in the run”, it was past the end of it. On any day the marker landed past roughly the halfway point of that range, the best thing in the game was a coin flip on the seed instead of something you could go and get.
It is now planted between the 9th and 45th piece. Trays four through fifteen, which is roughly the twenty second to ninety second window.
Nothing about reading that code would have told me. The range was internally consistent, seeded, tested, and wrong. The measurement now sits in a comment next to the number, so the next person to look at it knows it was counted rather than chosen by feel.
Time Had to Stop Being Time
The property I wanted was that two people playing the same day get the same puzzle, and that a recorded game replays to exactly the same result.
Score and board are easy enough. Remaining time is not, because a clock read inside the engine makes every run unrepeatable by definition.
So the engine never reads a clock. Every move carries how many milliseconds passed, as an argument. The interface owns the wall clock and tells the engine what happened; the engine has no idea what time it is. That one inversion is the only reason the real test can exist:
Same day, same sequence of moves, identical score, identical board, identical time left.
The other half of that is refusing to touch the random number generator during play. The day’s entire piece sequence, all six hundred of them, is drawn before your first move and never touched again. A test replays a full game and then checks that the plan is unchanged, byte for byte, because the failure mode here is silent: if placing a piece nudged the generator, two players would drift apart gradually and neither would ever notice.
The Thing I Did Not Build
The brief asked for a hashing function, a random number generator, and a secret build-time value to make it harder to compute future puzzles.
The hub already had the first two. Writing a second copy of a random number generator next to the existing one is not layering onto a system, it is starting a competing one, and in a year nobody remembers which is authoritative.
The secret went too, for a plainer reason: it does not do anything. There is no leaderboard and no score to defend, and anyone who opens the JavaScript can work out next week’s puzzles either way. It would have been a lock with no door, and the honest version is to not ship it and say why.
Earning the Uncapped Version
Play the daily three times and a practice mode opens, with a random puzzle and no ceiling on the clock at all.
Three times means three different days. Replaying today ten times does nothing, which is the entire point, and there are two separate tests for it because “complete it three times” quietly turning into “press the button three times” is exactly the kind of thing that rots without anyone noticing.
It is free. It rides the same mechanism the paid chapter unlocks use, with the price set to zero, so it did not need its own system. And the practice mode deliberately does not report anything back to the hub. It has a random puzzle, so letting it touch your streak would corrupt the thing the streak is supposed to mean.
Not Every Day Is The Same Difficulty Any More
Some days the board starts nearly empty. Some days a chunk of it is already occupied before you place anything.
The day’s seed picks one of three setups, Calm, Busy or Packed, roughly five to three to two. Calm is exactly what shipped originally, so most days are unchanged. The harder ones scatter more animals across the board at the start, and scattered is the operative word: fragmentation is what makes placement hard, far more than the raw number of filled squares.
The tier is drawn on its own separate stream of randomness. That sounds fussy and it is the whole reason the feature was safe to add: tuning how hard the days are cannot accidentally change which pieces you get or move the Golden Critter, because those come from different streams. It is also fixed by the day, not by the retry, so a hard day that needs the generator to try again is still a hard day rather than quietly becoming an easy one.
And if a Packed day genuinely cannot be cleared, it steps down to an easier setup rather than shipping. Hard is the point. Impossible is a bug.
Harder Was Not Harder, And Measuring Was The Only Way To Know
I had a check already that asks “can this day be cleared at all”. I assumed I could turn the difficulty up and watch that check start to complain.
It barely moved. The check wants one cleared line inside the first three trays, and filling more of the board in advance makes lines easier to complete, not harder. It was answering a question I was not asking.
So I measured the thing I actually cared about, the same way I found the unreachable Golden Critter earlier: let a dumb scripted player play until it gets stuck, and count how many pieces it managed to place.
| Setup | Pieces placed before getting stuck |
|---|---|
| Calm | 38 |
| Busy | 29 |
| Packed | 20 |
That is the gradient I wanted. A Packed day is about half a Calm one.
Then I tried to push Packed harder, and it got worse rather than harder. Filling even more of the board left the typical day no more difficult than before, while the unluckiest day collapsed to two pieces placed and then stuck. A day that is over before it starts is not a difficult day, it is a broken one.
This is the second time on this project that a number which looked completely reasonable written down turned out to be wrong in play, and the second time that reading the code would never have shown it. The setting I shipped is the one the measurements pointed at, not the one I first guessed.
The Score You Could Not See
Separately, and slightly embarrassing: the game had been recording your best score and how many days you had completed since the day it launched, and displaying them precisely nowhere.
The numbers were being written correctly the whole time. Nobody had wired them to the home page strip or the profile. Adding the two rows made every existing player’s history appear at once, because it had been quietly accumulating all along. No migration, no backfill, just a display that had never been connected.
What Is Not Done
I have not played it in a browser.
The determinism is tested, the dead-end detection is tested against every one of the thirty-two piece orientations, the clock ceiling is tested, the three-day rule is tested twice, and the difficulty setups are pinned so that no day can ship unclearable. Ten things are not: a real three minute run, catching the Golden, dragging a piece off the edge of the board with a thumb, reduced motion, and whether those seven colours are actually readable against the board background in all four themes rather than merely distinct from each other.
The difficulty measurements have their own gap, and it is worth naming. The scripted player I measured with is a poor one. A real person plans ahead and will last longer than any of those numbers, so treat them as a comparison between setups rather than a prediction of your run. And “clearable” is the only thing I can measure. Whether a Packed day is enjoyable is not something a test can answer.
It is live, which is not the same as verified, and those are two different claims.
Also worth saying plainly: this shipped in a commit that carries another session’s work alongside it. The two were tangled in the same files and could not be separated cleanly. The commit message says so at the top rather than leaving it for someone to discover.

