Disclaimer: The main points of this essay were written by a human, edited by an AI, and reviewed by the human once more.
Lessons Learned Vibe Coding an iOS App from Scratch
I've been a developer for over 7 years, primarily focused on Python and Machine Learning. For a long time, I've had the desire to build my own apps, but my lack of experience in frontend and mobile development was a constant source of frustration.
Everything changed with the recent rise of "vibe-coding." I discovered a newfound ability to build across the entire stack—frontend, backend, and infrastructure—regardless of my prior expertise. In fact, this very website was developed using Cursor and Claude.
With this new momentum, I decided to take on a challenge: publishing a vibe-coded iOS app from scratch. This blog post is a collection of the lessons I learned along the way, shared so that others can benefit from my journey.
The Lessons Learned
1. Choosing the Right Tools: IDEs and Models
The first step was deciding on the environment. In vibe-coding, your IDE and LLM are your primary collaborators. I weighed my options between Claude Code, Codex, and Cursor. Although I've since learned more about the others, I stuck with Cursor at the time because of my familiarity with it.
For the models, I had access to both Claude Sonnet 4.5 and GPT-5. I ended up developing a hybrid strategy based on their strengths:
- GPT-5-High: This became my primary workhorse. While it was a bit slower, it was incredibly methodological and precise. It was also more cost-effective, making it ideal for the bulk of the coding tasks.
- Claude Sonnet 4.5: Whenever GPT-5 hit a wall or when I needed a quick solution for complex logic, I switched to Sonnet 4.5. It was exceptionally fast and agile, though it came at a higher cost.
2. Framework Selection: The "Native-ish" Sweet Spot
Choosing the right framework was critical. I evaluated three main contenders: SwiftUI, React Native, and Flutter.
- SwiftUI (Xcode): Coming from a Python background, Xcode and Swift felt somewhat "alien." It reminded me of the heavy, monolithic IDEs from the Visual Studio era, and since I had never developed for the Apple ecosystem, the learning curve felt unnecessarily steep for a vibe-coding project.
- React Native: This felt too much like web development. The massive
node_modulesfolders, the heavy React dependency, and the layers of wrappers didn't appeal to me. I wanted something that felt more focused on the mobile experience itself. - Flutter: This turned out to be the balanced option. It provided a "native-ish" feel without the overhead of React Native or the steep barrier of entry of SwiftUI.
3. Solving a Real Problem: The "Not-Just-a-Wrapper" Realization
My goal wasn't to build a $1M+ MRR powerhouse; I simply had a specific problem I wanted to solve: real-time voice translation.
To achieve this, I chose OpenAI's GPT-realtime as the engine. With the right prompting, it works remarkably well. On the surface, the app was essentially a "wrapper" around this API. However, the process of building it taught me a humbling lesson: creating a truly great user experience around an AI wrapper is far from trivial.
When you're dealing with real-time audio, latency, and voice interactions, the "wrapper" part is actually the smallest piece of the puzzle. Most of the effort goes into making the interaction feel seamless—handling network interruptions, visual feedback for voice activity, and ensuring the interface doesn't get in the way of the conversation.
4. Backend Infrastructure: Staying Lightweight with Cloudflare
For the backend, I needed something that matched the speed and efficiency of the "vibe-coding" philosophy. I chose Cloudflare Workers, and it turned out to be the best decision for several reasons:
- Serverless & Scalable: It's extremely lightweight and handles scaling out of the box.
- Integrated Ecosystem: With a built-in database (D1) and KV storage, it felt like an almost complete "all-in-one" solution for serverless development.
- Email via Resend: The only missing piece in Cloudflare's core offering (currently in private beta) was email. I bridged this gap by using Resend, which was incredibly easy to integrate and maintain.
5. Mastering the Workflow: Read, Redirect, and Plan
The day-to-day development process was a fascinating experiment in human-AI collaboration. My workflow evolved through several distinct stages:
- The "Watch and Learn" Phase: Initially, I’d give broad instructions like "create email + OTP-based authentication" and simply watch the AI work. Even though I wasn't a Dart or JS expert, my 7+ years of experience in Python allowed me to read the code effectively.
- The "Active Redirection" Phase: As with any collaborator, AI sometimes goes off on a tangent. I learned early on that I couldn't just be a passive observer. I had to stop the process, provide feedback, and redirect the AI back to the intended path.
- The Breakthrough: Plan Mode: The biggest shift in productivity came when I discovered Plan Mode. Instead of having the AI jump straight into coding, I started asking it to outline its approach first. We would refine the plan together until I was satisfied, and then let it execute.
6. The Automation Secret: The Power of the Makefile
One of the most impactful decisions I made during development was asking GPT-5 to help me create a comprehensive Makefile. This wasn't just for compiling; it became the central nervous system of my development cycle.
make debug: This single command started the backend server locally, built the app, and launched it with all local environments configured.- The Flutter Advantage: Flutter was a game-changer here. For local debugging, I would run the app as a macOS desktop app rather than an iOS simulator. This made the feedback loop incredibly fast.
- Targeted Commands:
make androidhandled the build and deployment directly to my personal device;make deployautomated the backend;make screenshotsgenerated marketing materials; andmake publishhandled the App Store draft process.
7. The Final Hurdle: Navigating Apple's App Review
While the coding was fast, the final step—getting into the App Store—had its own set of challenges. It wasn't that the review itself was impossible to pass, but the logistics were surprisingly complex.
The biggest hurdle was understanding the dance between the build and the configuration of In-App Purchases (IAP). Figuring out how to submit the first IAP alongside the initial build for review was a bit of a puzzle. It required a fair amount of trial and error, cross-referencing documentation, and patience.
But eventually, the notification came through: Approved.
Seeing my own iOS app live on the Apple App Store was truly a "dream come true" moment. After years of frustration, I could finally send a link to friends and colleagues and say, "I built this."
8. The Reality Check: Manual Testing is Non-Negotiable
Vibe-coding is remarkably fast, but that speed comes with a hidden risk: opacity. When you're building in a new language or framework, many of the underlying nuances are invisible to you. This makes rigorous manual testing an absolute necessity.
I learned this the hard way by accidentally shipping a test build to the App Store—twice. Because I couldn't easily verify every detail of the final generated build, small configuration errors slipped through.
You don't need to know every line of the framework, but you must ensure the final build passes sanity checks, the happy path, and critical edge cases.
9. Beyond "AI Slop": The Developer as Creative Director
There is a valid concern in the industry about "shipping slop"—low-quality, AI-generated junk. I sympathize with this; I never want to ship bugs or subpar experiences. However, my goal is to solve real problems.
Working with AI during this project felt less like using a code generator and more like having access to a team of mid-level engineers for every specialized task—frontend, backend, automation, and even App Store optimization.
Ultimately, I am responsible for every line of code that gets shipped. The AI provides the labor, but I provide the vision. It is this human-driven guidance, creativity, and commitment to solving a problem that serves as the ultimate antidote to AI slop.
Conclusion
The journey from a "backend-only" developer to a published iOS app creator was made possible by the bridge that vibe-coding provides. It's not just about writing code faster; it's about removing the barriers that keep ideas trapped in our heads.
I have always wanted to do more than just write code—I wanted to write fiction, create games, build apps, and share ideas through creative storytelling. For a long time, these fields felt closed off to anyone who hadn't spent years specializing in them. AI has changed that, making it possible for anyone with a vision to build and create across disciplines.
However, this democratization comes with a caveat. I still believe a writer with deep, lifelong expertise is far superior to someone using AI to generate a story. In the same way, an experienced software engineer can spot subtle architectural flaws in AI-generated code that an average user might miss. As a society, our collective eye for "slop" will sharpen, and we will learn to value the depth that only human expertise brings to the table.
There are many problems still to be solved as we head into this future. But for now, if you've been sitting on an idea because you don't "know the stack," let this be your sign. Pick a problem you care about, choose your AI collaborator, and start vibing.
The world is waiting for your story, your app, and your vision.
Featured Project: XTranslate
The project referenced in this post is XTranslate, an app that provides real-time voice translation between Japanese and many other languages. It is specifically designed to offer a seamless interpreter experience for tourists, foreigners living in Japan, and Japanese people who frequently interact with international visitors.
Download XTranslate