Why AI Couldn’t Build My “Simple” App: V2.0

The second version of the app, my prize competition platform, was supposed to be the simplified, front-end-friendly build. I dropped Go, Docker, and complex containerization in favour of JavaScript, Supabase Functions, and Netlify. It felt like the right decision.
But even with a cleaner stack, I’ve hit friction... again.
This post documents the main issues I've faced building app v2, why they mattered, and what I'm changing moving forward. If you're considering a similar architecture, HTMX + Supabase + Stripe + PWA, some of this might sound familiar.
Overgeneration: When AI Builds Too Much
I used Cursor AI to scaffold large parts of the project. And it worked, too well.
Cursor generated dozens of files at once, covering everything from layouts to utilities to Netlify functions. The problem? There was no clear guidance on what each file did, how they connected, or which ones were safe to edit. It became overwhelming fast.
Lesson: Ask for smaller file generations. Use a checklist-style roadmap that explains file purpose, edit boundaries, and dependencies.
Supabase + Netlify = Confusion
Supabase Edge Functions are great in theory, but pairing them with Netlify-style Functions introduced friction:
- Where do the functions live?
- How do you test locally?
- Which runtime are we even using?
I lost time just getting authentication, ticket logic, and basic database functions working consistently across environments.
Lesson: Supabase is powerful, but hybrid hosting setups (like Supabase + Netlify) need tighter, opinionated documentation, or a starter repo that proves the full flow.
Stripe Integration Headaches
Payments were always going to be complex, but Stripe’s webhook and checkout flow caused particular pain:
- Webhooks weren't reliably triggering Netlify Functions.
- Ticket logic (e.g. assigning numbers, validating entries) had to be spread across multiple backend files.
- Syncing payment status with the UI was fragile.
Lesson: Stripe webhooks need isolated testing in development. Don't assume anything about post-payment state, test every edge case.
HTMX + Supabase Session Mismatch
HTMX made the frontend lean and fast. But it didn’t play nicely with Supabase’s client-side auth model. Pages rendered as if the user wasn’t logged in, even when they were.
I had to manually check session state, inject user data into HTML templates, and avoid any dynamic behaviour that relied on localStorage
.
Lesson: HTMX works best with server-side session handling. For client-side auth (like Supabase), you’ll need glue code, or move session logic to the backend.
The Frontend Pipeline Got Out of Hand
I started with Tailwind and HTMX, simple enough. But then I added SCSS. Then PWA config. Then Vite. Then PostCSS.
At one point, our build wasn’t loading any styles, and I wasn’t sure why.
Lesson: Don’t over-engineer your frontend pipeline in early stages. Ship plain HTML with Tailwind first, add PWA and SCSS when the app is stable.
Stack Fatigue Is Real
This was the second full rebuild of the app. The first died under Docker and Go. The second is being reworked now because of AI overgeneration and integration sprawl.
Each time I restarted, I made decisions to simplify, but complexity crept back in.
Lesson: Simplicity isn’t just a goal, it’s a practice. Every new tool, function, or folder should earn its place.
What’s Next
Here’s how I'm moving forward:
- Granular control: Smaller AI generations with clear documentation for each file.
- Minimal stack: HTMX + Supabase + Netlify + Tailwind, no extras until proven needed.
- Manual overrides: Avoid “magic” code—write what we can understand.
- Test each piece: Stripe, Supabase auth, PWA, each gets tested in isolation before integration.
I'm not giving up. This version of the app is going to ship. But I'm finally learning to treat complexity like scope creep, it sneaks in fast and can sink a project.
If you’ve ever restarted a project because it got out of hand, I’d love to hear your story. Let’s normalise learning through friction.
Comments ()