Update, 8 September 2026: The online leaderboards are no longer available because I am retiring the database-backed service rather than continuing to spend Netlify credits on this small prototype. The timed difficulty modes remain available in the demo.
Last weekend, I decided to make a platformer. Broadly, that means a game where you guide a character across platforms, gaps and obstacles, mainly by running and jumping. By the end of that weekend-ish coding spree, I had a browser-based speedrunning prototype I named Ledgephase 120, with multiple difficulty modes, a now-retired online leaderboard and considerably more automated testing than I would ever have expected for a small personal project. The demo runs on Phaser, a framework for building games in the browser.
The point was not to make a complete game. I wanted to see how quickly I could reach a convincing proof of concept for a browser-based speedrunning platformer. By “vibe coding”, I simply mean directing Codex conversationally and letting it write almost all of the implementation while I concentrated on steering, reviewing and playtesting.
This is not going to be a Codex tutorial, nor is it my attempt to make some grand argument about what AI means for programming. I want to write something more abstract about that separately. This is just the story of one of my vibe-coding adventures: what it felt like to build a demo this way, what worked surprisingly well, what did not, and how my role gradually shifted from programmer to some strange mixture of designer, playtester and overly demanding director.

An earlier build at the start of the original nine-section course.
My journey with platformers
This was not actually my first attempt at making a platformer. During the Christmas holiday at the start of 2024, I built a four-level prototype called Strawberry Saga in Unreal Engine (only available for macOS). At the time, I knew only the basics of Unreal. I had been following a 2D Unreal Engine course, then deviated from it to make my own game using existing pixel-art assets. Strawberry Saga had more conventional platformer stuff than what I made this time: enemies, spikes, saws, springs, animations and more visual polish.

Strawberry Saga, the Unreal Engine prototype I made at the start of 2024.
The difficult part was making everything behave properly. Character physics took ages, collision boundaries produced weird results, and moving sprites, spinning saws and springs all needed their own little pieces of implementation. I was learning as I went, with nobody sitting next to me who could inspect the whole project when something went wrong, and it took several weeks.
The funny thing is that despite Strawberry Saga arguably having more polished level design, the movement never felt quite right to me. It was a little sluggish and occasionally laggy. This demo is much simpler, but its movement feels dramatically better.
My favourite childhood Flash game: Give Up 2
One of the games I played a lot when I was younger was the old Flash platformer Give Up 2. What I remember most about it is the brutality. You would play a level, finally become comfortable with it, and then the game would add more obstacles and make you do it again. You would reach a point where you genuinely wondered how that same room could possibly become more difficult. Then it would. I loved that.
I later played Never Give Up on Steam, and that was the game whose movement I really fell in love with. It felt like a much more polished evolution of the same basic idea: double jumps, wall jumps and fast, responsive controls that made simply moving around satisfying. That side of it probably had the most direct influence on how I wanted this game to feel.
More broadly, precision platformers are built around exact movement, difficult jumps and repeated attempts until a section becomes familiar. In this demo, I wanted most of the difficulty to come from movement and geometry rather than enemies or spikes, with the timers and online leaderboard adding some speedrunning pressure.
When I started this project, I did not have a detailed design document. I did, however, have a very strong idea of how I wanted pressing the buttons to feel.

Never Give Up. Massive Monster, Tasselfoot, Armor Games Studios, press kit.
I started with the player, not the levels
One of the first things I asked Codex to make was essentially a movement playground. Instead of immediately building the level itself, I wanted somewhere I could run around while changing all sorts of player parameters in real time.
Acceleration, gravity, jump strength, air movement, coyote time, jump buffering, wall-jump behaviour, and various other bits of forgiveness could all be adjusted. I spent quite a while just playing with sliders, and this was probably my favourite part of the whole project.
There was a moment when the movement suddenly clicked and I thought: yes, this is basically exactly how I want the character to feel. I kept the tuning interface around for most of development, but after that point I only made relatively minor changes.

The development playground to tune the character’s physics.
That is also roughly how I interacted with the codebase in general. I was not completely blind to it. I would occasionally open files and glance at relevant values, especially later when I was manually tuning the time limits for each section.
My original idea did not really work
The first proper concept was not what I ended up building. Originally, I wanted an infinite vertical tower.
The interesting part, I thought, would be generating ledges probabilistically so that the tower became progressively more difficult through its geometry. I specifically did not want the usual endless-climber solution where the game simply scrolls faster and faster until the player cannot keep up. I wanted the jumps themselves to become harder.
This turned out to be much more difficult than I expected. Generating platforms is easy. Generating an endless sequence that remains possible, interesting, readable, varied, and progressively harder without degenerating into nonsense is not.
After enough experimentation, I gave up on the infinite tower. Instead, I switched to a finite sequence of fixed sections, with a timer for each section providing the speedrunning pressure.
The high-level idea behind the leaderboard survived the pivot. I had always wanted some competitive element so that people had a reason to try again. Originally, the leaderboard would simply have shown the maximum height reached. Once I added a finish line, that stopped making sense, so height in metres became completion time.
Level design
I did not meticulously design each section myself. Instead, I often told Codex to be creative and generate a bunch of level ideas, far more than I actually needed. Then I played them and cherry-picked the ones I liked.
I found this workflow really enjoyable. It was less like programming a level and more like being handed a pile of prototypes by an extremely fast junior game designer and saying:
This one is fun. This one is boring. Make this gap wider. Delete this whole section. This one looks difficult but actually isn’t. I discovered a mechanic here. Make me something based on that.
The final single-wall climb came directly from one of those moments. I found an unintended way to climb an earlier two-wall section by repeatedly returning to the same wall and gaining a little height each time. Instead of treating it as an exploit, I asked Codex to turn the technique into a challenge of its own.
Some of the supposedly hard levels Codex generated were also just physically impossible. Not “too difficult for me”, but impossible.
I eventually started asking Codex to prove that its harder sections could actually be completed and, for particularly questionable ones, generate recordings of an automated player completing them. That solved one problem and introduced another: the newly “verified” difficult levels were sometimes far too easy.
An automated route could establish that a sequence of jumps was possible. It could not establish that the section was enjoyable. The project log ended up full of cases where something was technically valid but felt wrong once I actually touched the controls, and that distinction became important.
Part of the automated proof for the nine-section course, crossing sections without human input.
I could build ideas faster than I could judge them
This was probably the biggest difference I noticed compared with Strawberry Saga. Back then, a new mechanic carried a fairly serious implementation cost. Now I could say, “What if we did this?” and usually have something to try very quickly.
I worried much less about whether an idea was worth implementing before implementing it. That is liberating, but it also lets you generate bad ideas at incredible speed.
Codex also had a tendency to overengineer things, or at least to solve them much more thoroughly than a weekend prototype needed. Part of my role became spotting when the lazy fix was actually the better one: simplifying a section, removing an option, or leaving a system alone.
The bottleneck moved. Instead of spending most of my time asking, “How do I build this?”, I spent much more of it asking, “Is this actually good?” My own playtesting was changing the specification underneath Codex while Codex was implementing it.
Then I made my friends play it
At some point, I decided that my own playtesting was no longer enough, so I recruited friends. “Recruited” is perhaps a generous word. A small but significant subset of my social circle was more or less forced to play the demo while I watched.
One thing I had perhaps underestimated was just how difficult it had become. To be fair, I was trying to make a precision platformer, so difficulty was not exactly an accident.
Still, my involuntary QA department consistently found the two-wall section and especially the final single-wall climb very hard. They also noticed things I had stopped noticing because I had spent so long with it.
For example, the jump is not binary. Holding the button longer gives you a higher jump, while releasing it early cuts the ascent. Several people commented on that explicitly.
Others were surprised that the character could jump upward through horizontal platforms and then land on top of them. I had become completely accustomed to one-way platforms, but some players expected them to behave like solid blocks.
Those reactions were useful because they reminded me that even extremely simple mechanics contain assumptions.
That feedback eventually changed the structure of the demo. Most new players never reached the end of the original nine-section course, so I split it into two shorter levels: a five-section introduction and a four-section advanced run. The advanced level is available immediately, so the split was less about progression than giving newer and more experienced players a meaningful finish line.
So, to everyone I cornered into playing it: thank you for your service.
“Should I add a leaderboard?” became a backend
The leaderboard might be my favourite example of how little friction there was in expanding the project. Could I have built a simple leaderboard myself? Probably. Would I have wanted to spend the time setting up the database, designing the schema, writing migrations, creating server endpoints and wiring everything together? Probably not.
With Codex, the process felt almost absurdly frictionless. The demo was already hosted on Netlify. Somehow, I went from asking for a leaderboard to having Netlify Functions talking to a managed Postgres database, with the tables and migrations handled through code.
Then came the question of cheating. A browser can always lie to a server about what happened locally, so eventually Codex built a replay verifier.
Phaser handles the rendering and browser-facing parts of the demo, while the movement and collision rules live in a separate deterministic TypeScript simulation running at a fixed 120 Hz, or 120 simulation steps per second. That simulation rate is also where the 120 in Ledgephase 120 comes from. Instead of merely submitting “I finished in 30 seconds”, the browser recorded the player’s inputs. The server could then replay those inputs through the same simulation and verify that they actually reached the finish on the claimed step.

The original full-course leaderboard as of August 29, 2026, before the demo was split into two levels.
My friend responded by training an AI to beat it
I feel lucky to be possessed by the wonderful curse of being surrounded by smart yet lazy people. One of my friends proved the point beautifully: instead of playtesting the demo, which was what I had actually asked him to do, he decided to train an AI to play it for him.
Replay verification can prove that an input sequence reaches the finish, but it cannot prove that a human produced it. With Claude, my friend extracted the simulator, created and verified a fast training environment, and trained a reinforcement-learning agent to speedrun the demo.
The trained agent finished the original nine-section course in 23.83 seconds, fast enough to beat even the then-current Hardcore time limits by a significant margin. It briefly took first place on the original full-course leaderboard under the username ‘SPAYDIRMAN’. After I split the demo into two levels, the run was no longer compared with current times, and the leaderboard itself has since been retired.
So, how did vibe coding actually feel?
For a personal project like this, I found it amazing. I went from an idea to something I could send to friends in a few days. I could experiment far more aggressively than I would have if every feature required me to personally understand and implement all the details first.
I still occasionally ran SQL queries while testing the leaderboard with sample scores, handled a few Git operations manually, and gave Codex small workflow tips. For example, I asked it to make a habit of working through pull requests so Netlify would generate Deploy Previews, instead of wasting credits on production deploys from main.
Vibe coding did not mean switching my brain off. Codex could implement almost anything I asked for, but of course it could not decide whether I should have asked for it in the first place.
The final result pleasantly surprised me: the prototype feels better to control than the platformer I spent several weeks building the old-fashioned way. I hope to turn it into a larger speedrunning game one day. If I do, the real challenge will not simply be making more of it; it will be deciding which ideas are actually fun enough to keep.