I Built a Production App Using Three AI Tools — Here's What Actually Worked

I Built a Production App Using Three AI Tools — Here's What Actually Worked

How I used multiple AI tools as a virtual product team to ship a real MVP — and where the cracks started to show.


I didn’t use AI to build a demo. I used it to ship a production-ready app.

Most stories fall into one of two categories:

  • Toy demos that never ship
  • Vague claims like “AI built 80% of the app”no structure, constraints, or accountability

This post is about neither.

Over the past weeks, I built OctaPicks, a real consumer web app that lets users make UFC predictions and compete with friends. It’s live, deployed to production, and already has real users.

In the process, I had to deal with many challenges, and make many choices. It turns out that what made the biggest difference wasn’t which AI tool I used.

It was treating AI as a virtual team with explicit roles, decision ownership, and veto power.


The App (Quick Context)

OctaPicks is a UFC fight prediction platform where users commit to picks before fights start, compete in private or public groups, and are ranked automatically once results are final.

What begins as a simple “who do you got?” mechanic quickly turns into a system with timing rules, fairness constraints, and social pressure.

This mix alone (real-time constraints, gamification, and social mechanics) made it a solid test case for building a production MVP with AI, not just a demo.


The Stack (High Level)

I intentionally built OctaPicks as a zero-server, edge-first system. Not because it’s trendy, but because it forces architectural decisions to surface early — especially around consistency, background jobs, and state transitions. The frontend is a modern React SPA hosted in Cloudflare Pages, while the backend runs entirely on Cloudflare Workers. Predictions, scoring, and rankings live behind a serverless API backed by a relational database, which turned out to be a good stress test for AI: correctness mattered, timing mattered, and “close enough” wasn’t acceptable.

Concretely, this meant React and Vite on the frontend, Cloudflare Workers with Hono for the API, and Neon PostgreSQL for relational data. In hindsight, the stack wasn’t about elegance — it was about forcing decisions early and making mistakes visible.


The Core Idea: A Virtual AI Team With Roles

Once the technical constraints were in p, the bigger problem wasn’t tooling — it was decision ownership.

Early on, I noticed a recurring failure mode: AI answers often sounded authoritative even when they weren’t particularly good. That’s when I stopped treating AI as a single assistant and started treating it as a team with defined roles, boundaries, and veto power.

The biggest mistake people make with AI is asking it to do everything at once, assuming it can capture every point of view in a single response.

To circumvent this limitation, I defined a default role stack, a minimum effective team implied by the product, ordered by decision gravity:

  1. Product Manager (Consumer App)
  2. Senior UX / UI Designer
  3. Gamification & Retention Designer
  4. Growth / Acquisition Specialist
  5. Brand Strategist
  6. Front-End Platform Engineer
  7. Backend / Systems Engineer
  8. UX Writer (on demand)

This order is practical, not philosophical.

Its importance only became obvious when I ignored it. That’s when I ended up with features that looked good but didn’t rvive real usage. AI is particularly good at producing visually polished but useless features, clever mechanics nobody understands, or technically elegant systems nobody uses — unless it’s constrained.

What actually hurt in those moments wasn’t just the outcome, but the loss of clarity. I no longer knew what I was optimizing for: gamification, usability, engagement, brand, or engineering correctness. Most product decisions are trade-offs, and when I wasn’t explicit about which dimension mattered most, AI optimized confidently — just in the wrong direction.

Takeaway: AI doesn’t make bad decisions. It makes unowned ones.


Decision Ownership and Veto Power

Each role had explicit veto power, limited to its domain:

  • Product goals, scope, priorities → Product Manager
  • Interaction clarity and hierarchy → Senior UX/UI Designer
  • Motivation mechanics and scoring psychology → Gamification Designer
  • Shareability and acquisition hooks → Growth Specialist
  • Naming, tone, brand consistency → Brand Strategist
  • Feasibility under tooling constraints → Front-End Engineer
  • Data correctness, idempotency, sequencing → Backend Engineer
  • Microcopy clarity → UX Writer

Hard rule:

  • No role vetoes outside its domain
  • If multiple domains conflict, Product resolves

This alone mattered more than any individual AI model.


How the AI Tools Actually Fit Together

Over time, I stopped thinking about the AI tools as software and started thinking about them as people on a virtual team. Not in a metaphorical sense, but in a very practical one: each had a role, a temperament, and a cost — and each caused problems when I asked it to operate outside its lane.

ChatGPT was “The Brain.”

This is where most of the product thinking happened. The Brain sat closest to the top of the Virtual Team Framework, filling the roles of Product Manager, UX reviewer, and early-stage strategist. I used it when decisions were still fluid: shaping features, reasoning through edge cases, reviewing UX flows, and stress-testinbefore they hardened into code. It was excellent at helping me clarify intent and explore alternatives, but it didn’t naturally enforce long-term consistency unless I did.

The Brain helped decide what we should build, not how to build it.

Claude was “The Architect.”

Whenever the problem crossed into deep engineering territory, this is where I went. The Architect aligned most closely with the Backend / Systems Engineer role in the framework. It was slower, more deliberate, and far less tolerant of vague reasoning. It was also noticeably more expensive, and I regularly ran into token limits, which forced me to be selective. That friction turned out to be useful. Claude wasn’t for exploration, it was for moments where correctness mattered, background jobs had to be idempotent, and architectural changes couldn’t afford to be “almost right.”

The Architect didn’t move fast, it made sure things wouldn’t collapse later.

Cursor was “The Worker.”

Most of the implementation lived here. The Worker mapped cleanly to the Front-End Platform Engineer role: fast, tireless, and highly effective when the task was well-defined. Given clear instructions and constraints, Cursor excelled at scaffolding features, wiring components together, and pushing work across the finish line. But it rarely questioned assumptions. If a design decision was shaky, The Worker would happily build on top of it and make it harder to unwind later.

The Worker shipped what it was told, not what it should have questioned.


What became clear over time is that none of these tools failed on their own. They failed when I blurred accountability. The Brain struggled with long-term structural discipline. The Architect was wasted on UX or naming. The Worker optimized relentlessly for momentum, even when it shouldn’t.

Once I treated them as specialists inside a clear decision framework, with explicit roles and veto boundaries, everything improved. The tools didn’t replace product judgment. They amplified it. And when ownership was weak, they amplified that too.

That separation of roles mattered far more than which model was “best.”


What Didn’t Work (And Why That Matters)

As the project grew, the first thing that started to hurt was entropy.

A lot of generated code was redundant. Components overlapped. Utilities solved the same problem in slightly different ways. Libraries were reintroduced under new shapes. Environment variables multiplied. None of this happened at once, it emerged gradually as more screens, routes, features, and database tables were added. AI optimizes locally unless you actively enforce global discipline, and over time that local optimization turns into clutter. There is still cleanup to do.

The second issue was more subtle: authority bias.

Many AI-generated ideas sounded confident and well-reasoned, even when they weren’t particularly strong. Some suggestions were genuinely good, but others felt templated or derivative, ideas you’ve seen a hundred times before, delivered with enough confidence to pass a quick sniff test. This meant I had to put the product owner hat on frequently, not just to choose between options, but to actively reject decisions that didn’t align with my reasoning. Without that filter, it would have been easy to drift into “good-sounding” but weak product choices.

The third friction point showed up at the architectural level.

As implementation accelerated, especially inside Cursor, some design decisions solidified too early. Short-term patterns became defaults. Earlier assumptions were reinforced rather than questioned. A few architectural choices had to be revisited and improved later, not because they were impossible to fix, but because the AI had optimized for momentum rather than long-term soundness. That’s a great way to ship an MVP, but it does leave technical debt behind.

None of this invalidates the approach.

Using AI this way worked extremely well to get a real MVP into production quickly. But it also made something very clear: AI accelerates building, not understanding. As complexity increases, context has to be actively maintained, decisions have to be reasserted, and product ownership becomes more important, not less.

That trade-off (i.e. speed now, cleanup later) is exactly what you’re signing up for.


Reality Check

This approach worked extremely well to:

  • Build a real MVP
  • Deploy it to production
  • Validate the product

BUT, it also left:

  • Loose ends
  • Technical debt
  • Cleanup work

Which is exactly what you’d expect from a fast MVP, whether or not you use AI to build it.

The difference is speed, not perfection.


Final Takeaway

AI didn’t build the app for me.

But treating AI as a disciplined, role-based team:

  • Accelerated decisions
  • Reduced cognitive load
  • Enabled faster iteration without losing control

AI didn’t replace product judgment in this project, it amplified it. For better and for worse.

👉 If you’re curious about the result: www.octapicks.app

Read next