Crumbongo started as a tiny Chrome extension experiment.
The original mechanic was deliberately strange: take the number of accessible cookie records from a website the player chooses and turn that number into game currency.
At first, that was almost the entire product.
Check a site. Harvest its cookie count. Spend the cookies.
But once I started adding progression, cosmetics, habitats and companions, the project began feeling less like an experiment and more like a small game.
That raised a new question:
How far could I push a game that still lived entirely inside a Chrome extension?
Eventually, that led me to build two minigames without using a traditional game engine and without turning the project into a large framework-based web application.
The constraints
Crumbongo is built with:
- vanilla JavaScript
- HTML
- CSS
- Chrome Extension APIs
requestAnimationFrame
- local browser storage
There is no Unity, Godot, Phaser, React, TypeScript or dedicated game framework.
Even the minigames use regular DOM elements rather than Canvas.
That was not originally a philosophical decision. Crumbongo had already been built as a lightweight extension, and introducing an entirely different rendering architecture just for two small games felt unnecessary.
So I decided to work with the environment I already had.
That limitation ended up influencing the game design much more than I expected.
Monkey Climb
The first minigame was Monkey Climb.
The concept is simple: Bongo climbs vertically, collects bananas, avoids hazards and earns additional cookies for the main game.
The important part was that the minigame could not feel disconnected from the rest of Crumbongo.
Rewards therefore go into the player's Cookie Jar, while lifetime progression remains tied to the core harvesting mechanic.
That separation matters.
If minigames increased lifetime progression directly, players could ignore the feature that makes Crumbongo different and simply grind the arcade game.
The minigame needed to complement the core loop, not replace it.
That was one of the first places where the project stopped being purely a programming exercise and became a game-design problem.
Cookie Stack
The second game, Cookie Stack, created a different challenge.
Cookies fall from the top of the play area while the player moves Bongo horizontally underneath them.
Catch a cookie and it becomes a physical piece of a tower.
The entire tower moves with Bongo.
Miss a normal cookie and you lose a life.
Golden cookies are rarer and worth more points.
Bombs can also fall. If one hits Bongo or the tower, the player loses a life, but the existing stack remains intact.
The game runs for 40 seconds with three lives.
Technically, getting the basic system working was relatively straightforward.
Making it feel fair was not.
When working code still feels wrong
My first version allowed the stack to keep growing.
From the code's perspective, this worked.
Every successful catch increased the tower height and the next cookie could land on top of it.
The problem only became obvious when I actually played it.
After enough catches, the tower became so tall that the next incoming objects had very little distance left to travel before reaching the catch area.
The game became increasingly difficult for a reason that did not feel intentional.
Nothing was technically broken.
It just wasn't fun.
I tried adjusting speeds and spacing, but the cleanest solution was much simpler:
clear the tower after five pieces.
The score continues.
The timer continues.
Lives continue.
Only the physical tower resets.
That tiny rule change made the game dramatically more readable and fair.
It also reinforced one of the biggest lessons I took from the project:
implementation can tell you that a mechanic works, but only playing it tells you whether the mechanic should exist in that form.
DOM elements as game objects
Building the games with DOM elements created some unusual constraints.
Objects still need:
- position
- movement
- collision areas
- timing
- state
- cleanup
- layering
But instead of sprites inside an engine, they are elements being updated in the browser.
requestAnimationFrame drives the gameplay loop.
The JavaScript updates positions and checks interactions, while CSS handles much of the visual presentation.
For a larger game, I would not recommend pretending the DOM is a general-purpose game engine.
For Crumbongo, though, the limitation was useful.
The games are intentionally small.
Sessions are short.
The number of simultaneous objects is limited.
And most importantly, the implementation stays consistent with the rest of the extension.
Progression changes game design too
The minigames also forced me to think about the economy around them.
Crumbongo has two related values:
- the current Cookie Jar balance
- lifetime cookies used for progression
The distinction allows me to reward minigame play without creating an easy way to bypass the primary mechanic.
A good Cookie Stack run can give you cookies to spend.
It cannot artificially accelerate your lifetime progression.
That sounds like a small implementation detail, but it changes how the entire system behaves.
Once a game has currency, progression and unlocks, every new source of rewards affects the value of everything else.
Prices, unlock levels and reward tiers suddenly become connected.
I spent more time adjusting those relationships than I expected when I first added a simple level bar.
Keeping the extension local
There was another constraint I did not want to compromise on.
Crumbongo's core mechanic involves browser cookies, so I wanted the privacy model to remain extremely simple.
The game uses only the number of accessible cookie records returned for a site.
Cookie names and values are never stored or transmitted.
Browser cookies are never modified or deleted.
There is no gameplay backend, account system, analytics or tracking.
Persistent game state stays locally in the browser.
That also means the minigames needed to fit into the same local architecture instead of introducing a server simply because the project was becoming more game-like.
AI-assisted development
I also used AI-assisted development tools during the project, particularly Codex for implementation and iteration.
The useful workflow was not:
prompt -> finished feature
It was closer to:
define a narrow change -> implement -> run it -> play it -> inspect the result -> adjust -> repeat
AI was very effective at accelerating localized implementation work.
It was much less useful as a substitute for deciding whether a mechanic actually felt fair, whether a reward was motivating, or whether a visual element was positioned correctly.
Cookie Stack's tower limit is a good example.
A model could implement an infinite stack perfectly.
The important decision was realizing that I did not want one.
What I learned
Crumbongo is still intentionally small.
That is probably why these constraints worked.
Building two minigames without a game engine forced me to think carefully about what each game actually needed instead of immediately reaching for a larger technical solution.
More importantly, it reminded me that game development is full of situations where perfectly functional code produces a bad experience.
The interesting work often begins after the feature is technically complete.
If you want to see the result, Crumbongo is free:
https://crumbongo.teobella.com/
Chrome Web Store:
https://chromewebstore.google.com/detail/crumbongo/glnecpfjdlljaihbnmaijkaldfbhalfj
I'm especially curious how other developers approach this boundary.
At what point does a small browser game become complex enough that you would stop using the DOM and move to Canvas or a dedicated game framework?