A Product Manager’s journey from idea → shipped game, using AI as a true build collaborator
I’m a Product Manager by trade.
I’ve spent years writing PRDs, prioritizing backlogs, running sprints, and partnering with engineers to ship products. But for a long time, I carried a quiet frustration:
I had ideas I could clearly describe — but couldn’t personally build.
Last weekend, that changed.
I built Olè – The Lagos Hustle, a fully playable 3D endless-runner game with a global leaderboard and shipped it to production. Not as a side demo. Not as a Figma prototype. A real, live game.
What unlocked this wasn’t suddenly becoming a game engineer — it was using AI the way a strong PM uses people.
This is the story of how I treated AI like a junior engineer, applied product thinking end-to-end, and closed the gap between vision and execution.
The Idea: A Product Vision First
I wanted to build something fun, culturally grounded, and immediately playable.
Think Subway Surfers, but set in Lagos — danfo buses, street markets, wire fences, palm trees, local food collectibles. Fast. Chaotic. Familiar.
From a PM lens, I already knew the MVP scope:
- Three-lane movement (left / center / right)
- Jump + slide mechanics
- Progressive difficulty curve
- Global leaderboard to drive competition
- Mobile-first controls (thumb-friendly) What I didn’t have was deep game-engineering experience — and that’s where AI came in.
The Build: Treating AI Like a Junior Engineer
Instead of asking AI to “make a game,” I worked the way I would with an engineer on my team.
Clear Requirements Beat Clever Prompts
Bad prompt:
“Make me a fun game.”
Good prompt:
“Create a 3D endless runner using Three.js. The player auto-runs forward. Three lanes. Left/right to change lanes. Up to jump, down to slide. Obstacles spawn ahead and recycle.”
I wrote user stories, acceptance criteria, and constraints — just like I would in Jira.
AI didn’t guess what I wanted. It built exactly what I specified.Sprint-Based Iteration (Not One Big Build)
We shipped incrementally:Sprint 1 – Core movement, camera, obstacle spawning
Sprint 2 – Lagos theming (danfos, stalls, environment)
Sprint 3 – Scoring + collectibles
Sprint 4 – Leaderboard + persistence
Sprint 5 – UX fixes from real player feedback
Each sprint ended with:Me playing the game
Writing bugs like a PM
Feeding them back to AI as implementation tasks
AI handled execution. I handled prioritization and judgment.User Feedback → Product Insight → Code Changes
This is where PM thinking mattered most.
Feedback:
“The wire obstacle looks like I can jump over it.”
That’s not a bug — that’s a UX mismatch. Fix wasn’t logic; it was visual affordance.
✅ Solution: add barbed wire + mesh so sliding is visually obvious.
Feedback:
“Around 1100 points, the game feels like it slows down.”
Instead of blindly fixing it, I asked why.
Root cause: an ease-out speed curve that plateaued mid-run.
✅ Solution: linear speed scaling with a cap — consistent difficulty, no perceived slowdown.
This wasn’t AI intuition — it was product diagnosis, implemented by AI.
Tech Stack (Simple by Design)
- Frontend: Vanilla JavaScript + Three.js (WebGL)
- Backend: Node.js HTTP server
- Database: PostgreSQL (leaderboard persistence)
- Hosting: Replit (dev + prod) No React. No bundlers. No over-engineering. For this product, simplicity shipped faster.
What AI Changed for Me as a PM
AI Isn’t Magic — It’s a Teammate
AI didn’t “figure it out.”
It responded to:
- Clear requirements
- Defined success
- Structured feedback Sound familiar? That’s product work.
Domain Knowledge Still Matters
AI wrote the code — but it didn’t decide:
- What makes difficulty feel fair
- Why mobile controls need repositioning
- How obstacles should visually communicate risk AI executes. PMs decide.
Speed Is the Real Breakthrough
What would’ve taken me months of learning took one weekend.
Not because AI replaces engineers —
but because I could focus on what to build, while AI handled how to build it.
The Results (So Far)
- Build time: ~20 hours
- Codebase: ~2,000 lines
- Leaderboard players: 50+ in week one
- Iterations: 5 major versions driven by feedback And most importantly — a shipped product.
Try It Yourself
🎮 Play the game: ole-game.com
If you’re a PM with ideas stuck in your head — this is your sign.
The gap between product vision and working software has never been smaller.Appendix: Technical Deep Dive for Engineers
For those who want to look under the hood 👇
3D Rendering Architecture (Three.js)
The game uses a fixed player with the world moving toward the camera to create the endless-runner illusion.
// Object pooling for obstacles
const VISIBLE_DISTANCE = 100;
const SPAWN_DISTANCE = 80;
function updateObstacles(delta) {
obstacles.forEach(obstacle => {
obstacle.position.z += gameSpeed * delta;
if (obstacle.position.z > 10) {
obstacle.position.z = -SPAWN_DISTANCE;
obstacle.position.x = lanes[Math.floor(Math.random() * 3)];
}
});
}
This keeps physics simple and avoids unnecessary transforms.
Collision Detection (Performance-First)
Bounding boxes instead of mesh collisions:
function getPlayerBoundingBox() {
const box = new THREE.Box3().setFromObject(player);
if (isSliding) {
box.max.y = box.min.y + (box.max.y - box.min.y) * 0.4;
}
return box;
}
Sliding dynamically shrinks the hitbox — simple and performant.
Speed Progression Curve (Bug → Insight → Fix)
// Old (felt like slowdown)
const speedMultiplier = 1 + (maxSpeedBonus * (1 - Math.pow(0.99, score)));
// New (consistent)
const speedMultiplier = 1 + (score * 0.0005);
const clampedSpeed = Math.min(speedMultiplier, maxSpeedMultiplier);
Linear scaling + cap = predictable challenge.
Mobile Touch Controls (UX-Driven)
controlsContainer.style.cssText = ;
position: fixed;
bottom: 15%;
left: 50%;
transform: translateX(-50%);
pointer-events: none;
button.addEventListener('touchstart', e => {
e.preventDefault();
handleInput(action);
}, { passive: false });
Thumb-reachable, no accidental scrolls, no delay.
Leaderboard Persistence (Postgres)
async function updateScore(username, score) {
const existing = await pool.query(
'SELECT score FROM leaderboard WHERE LOWER(username)=LOWER($1)',
[username]
);
if (!existing.rows.length || score > existing.rows[0].score) {
await pool.query(
'INSERT INTO leaderboard (username, score) VALUES ($1, $2) \
ON CONFLICT (username) DO UPDATE SET score = EXCLUDED.score',
[username, score]
);
}
}
Only personal bests update — no leaderboard spam.
Weekly Reset (Competitive Seasons)
INSERT INTO leaderboard_archive (username, score, week_ending)
SELECT username, score, CURRENT_DATE FROM leaderboard;
TRUNCATE leaderboard;
Performance Optimizations
Geometry instancing for repeated assets
Frustum culling (Three.js default)
Texture atlasing
requestAnimationFrame-driven loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
if (!isPaused) {
updatePlayer(delta);
updateObstacles(delta);
checkCollisions();
}
renderer.render(scene, camera);
}
File Structure
/
├── index.html
├── style.css
├── game.js
├── server.js
└── assets/
No build step. No bundler. Just working code.
Final Thought
AI didn’t replace engineering.
It collapsed the distance between idea and execution — especially for people who already know how to think in systems, tradeoffs, and outcomes.
If you’re a PM, designer, or builder who’s been waiting to “one day build” — that day is now.
Top comments (3)
Thamks!
This echoes my own experiences building an Arkanoid style game.
Planning, clear requirements and splitting the implementation into small logical chunks is key.
One thing I noticed is that the implementation often uses outdated practices (training cutoff date) which you have to address semi manually.
BTW, can you fix the formatting, so that the source code renders properly, it makes it hard to read ;-)
This is a really inspiring build story 👏
Love how you frame AI as a junior engineer and apply pure PM discipline — clear requirements, sprinting, feedback loops. The emphasis on shipping, simplicity, and product judgment over tools is spot on. Proof that systems thinking + AI can turn ideas into real products fast.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.