Hi! I’m Nika, I’m 22, and a few months ago I decided to build my first iOS app. I wanted to make something I would genuinely use myself, publish it on the App Store, and see whether it could be useful to other people too.
The idea was simple: I wanted a beautiful focus timer that would help me stay away from distracting apps while giving me enough data to understand where my focused time was actually going. About a month later, that idea became Immerse — a real iOS app for Pomodoro sessions, studying, deep work, reading, and everyday focus.
I built most of it using Claude Code and Codex, and one of the strangest parts of the whole experience was that I didn’t manually edit the code myself. Instead, I described what I wanted in normal language, tested what the AI built, found problems, and kept iterating.
That process taught me that vibe coding is not really about writing one perfect prompt and watching an app magically appear. The coding part can become dramatically faster, but someone still has to decide what to build, how it should work, whether the result is good, and when an idea simply needs to be thrown away.
Here’s how I went from an idea for a focus timer to shipping my first iOS app.
Why I decided to build a focus app
I’ve always enjoyed studying, both in high school and at university, and the Pomodoro technique was one of the productivity methods that genuinely worked for me. Over the years, I tried almost everything: “study with me” videos on YouTube, study Discord communities, different productivity techniques, and more focus apps than I can remember.
But I could never find an app that felt completely right. Some were useful but visually boring, others looked great but barely showed any interesting statistics, and some tried to become complete productivity systems with projects, tasks, calendars, habits, subscriptions, and dozens of screens I didn’t need.
I wanted something much simpler. The app had to look good enough that I would actually enjoy opening it every day, with different backgrounds, customization, and a clean interface. At the same time, I wanted detailed statistics that would let me explore my focus data instead of simply telling me that I had completed five Pomodoros today.
Eventually, I had a pretty obvious thought: if I couldn’t find the focus app I wanted, why not try building it myself?
I started by studying other apps
Before building anything, I downloaded dozens of focus and Pomodoro apps and started testing them. I looked at their interfaces, features, settings, timer behavior, statistics, personalization, and all the tiny UX decisions that make an app either pleasant to use or something you want to delete after five minutes.
I also asked Claude to help me analyze user reviews more systematically. I didn’t want to base the product entirely on my personal preferences, so I looked for patterns in what real users repeatedly praised or complained about in existing focus apps.
I collected the things I liked, the things I hated, and the things I thought were missing. Gradually, I started forming a much clearer picture of what Immerse should be.
The goal was never to clone one successful app. I wanted to combine ideas that worked, remove the things that constantly annoyed me, and add some ideas of my own.
Designing the timer
One of the first things I wanted to figure out was the timer itself. I’ve always liked timers that show the passage of time visually instead of simply displaying the exact number of minutes and seconds remaining.
That idea became the foundation of Immerse. I wanted someone to be able to glance at the timer and roughly understand how much time was left without necessarily reading the numbers.
But I also didn’t want everyone to be stuck with one visualization. Together with Claude, I experimented with different ways of displaying time inside a circle, and eventually I ended up with five timer styles.
Lap moves a line around the inside of the circle. Pie gradually removes the filled area like slices disappearing from a cake. Ring reduces the circular outline as the session progresses. Digits is a classic countdown for people who prefer something familiar, while Bubble uses a gradually filling sphere.
I also added minute markers around the timer. The number of markers corresponds to the length of the session, so they give you another visual representation of time. Users can turn them off completely or choose between dots, lines, squares, hearts, and flowers.
None of these details changes the fundamental purpose of a Pomodoro timer, but they change how the product feels. Since this was an app I expected people to keep open while studying or working, that mattered to me.
Customization became a bigger part of the app than I expected
I care a lot about the appearance of the apps I use every day. If something is going to stay on my screen for hours while I work, I want it to create the right atmosphere rather than look like another generic utility.
I started with seven gradient backgrounds and four image backgrounds: a sunset, mountains, a forest, and the northern lights. That already made it possible to completely change the mood of the timer, but I quickly realized there was an obvious limitation: I could keep adding backgrounds forever and still never create something everyone liked.
So I added the ability to choose any photo from your own library as the timer background. It can be a favorite city, the sea, your desk, a photo from a trip, your pet, or literally anything else. Instead of trying to decide what the perfect focus screen should look like, I could let each person create their own.
Then the actual vibe coding started
Once the concept and visual direction were clear enough, I started building the main screen with Claude Code. I followed a fairly simple MVP approach: get the main interaction working first, then gradually build everything around it.
I described the layout, buttons, timer behavior, and interactions in normal language. Claude would implement them, I would run the app, look at the result, and explain what needed to change.
What surprised me was how far I could get without manually going into the code and fixing things myself. I was building a working iOS application largely through natural-language instructions.
But I quickly learned that this doesn’t mean the human disappears from the process. I still had to make all the product decisions, test every important interaction, notice when something felt wrong, explain the problem clearly, and decide whether the result was actually good enough.
That became one of my biggest lessons from the whole project: AI can implement a decision very quickly, but you still need to make the decision.
Building the rest of the product
Once I was happy enough with the main timer, I started building the other parts of the app. Users could create different activities, choose what they were about to work on, and set different focus and break durations for each one.
I spent a surprising amount of time on small UI details. I constantly looked at how similar interactions worked in other iOS apps, which interface patterns already felt familiar to users, and which ones made the most sense for Immerse.
Sometimes Claude also suggested ideas I hadn’t considered. I didn’t automatically accept them, but having something that could quickly propose alternative approaches was useful, especially when I was stuck between several possible designs.
The process became very iterative. I would build one thing, test it, make sure I hadn’t broken something else, refine it, and only then move to the next feature.
Voice prompts made AI development much faster
One unexpectedly useful tool during development was Wispr Flow. Instead of typing every prompt to Claude, I started dictating them.
At first, this sounds like a tiny improvement. But when you’re constantly describing visual changes, bugs, interactions, spacing problems, text changes, and lists of small fixes, writing everything manually gets surprisingly slow.
With voice input, I could keep the app open in front of me and simply describe what I was seeing. I could notice several problems on one screen and talk through all of them while still looking at the UI.
For this type of AI-assisted development, it made the workflow feel much more natural. I was spending less time writing instructions and more time looking at the actual product.
I stopped giving Claude one tiny task at a time
My first workflow with Claude was extremely simple. I would send one feature or change, wait for it to finish, open the app, test the result, find another problem, and send another prompt.
It worked, but it required constant attention. I always had to return to the agent, check whether it was finished, test the build, and immediately continue the conversation.
Eventually, I switched to a workflow that was much better for me. While testing the app, I started keeping a list of everything I noticed: bugs, UI problems, copy that needed changing, spacing issues, small behavior changes, and other improvements.
Then I grouped related tasks and sent Claude a structured list. For large new features, I still preferred a separate prompt so the agent could focus on one system, but batching small fixes was much more efficient.
This meant Claude could work for longer without me constantly watching it. I could do something else, come back later, test each item, write down my feedback, and prepare the next batch.
That change made vibe coding require much less continuous attention from me.
Building statistics was especially important
Statistics were one of the main reasons I wanted to build my own focus app in the first place. I didn’t want to show users a single number representing how many minutes they had focused that day.
I wanted completed sessions to turn into data that was genuinely interesting to explore. That meant showing how much time you focused, which activities received that time, how your focus changed across different periods, and what patterns appeared over days, weeks, months, and longer periods.
As I used the app myself, this part became easier to design. I could see which statistics I actually checked and which ones looked useful in theory but weren’t particularly interesting in everyday life.
That happened with other features too. Sometimes I would design something that seemed great, build it, and then barely use it. Other times, a tiny detail I almost ignored during planning would become something I relied on every day.
Eventually, I realized that using my own app was more useful than almost any prompt I could write. Real usage exposed awkward interactions and unnecessary features immediately.
App blocking came later
The first release wasn’t the end of the project. Once Immerse was running on my phone — and eventually on other people’s phones — I kept finding things I wanted to improve.
One of the larger features I added later was app blocking. Users can choose distracting apps before starting a focus session, and those apps are restricted while the timer is running.
It felt like a natural extension of the original idea. A focus timer can tell you to work for 25 minutes, but that doesn’t help much if TikTok, Instagram, YouTube, or another distraction is one tap away.
I also continued adding new statistics, refining existing features, and changing things based on actual use. Immerse didn’t grow according to one huge roadmap I wrote before development started. It grew through repeated cycles of building, using, noticing problems, and improving.
AI made that kind of development much easier because experimenting became relatively cheap. I could try a feature, live with it for a while, decide whether it actually improved the app, and then keep it, change it, or remove it.
Vibe coding is fast — and that creates a new problem
The biggest advantage of building with AI was obvious: speed. If I wanted to try a different timer visualization, change an interaction, add another statistics component, or experiment with a new idea, I could get to a working version much faster than I expected.
But there’s a downside to that speed. When creating a new feature becomes extremely easy, creating too many features becomes extremely easy too.
I had to learn that just because I could ask Claude to add something didn’t mean I should. Every new feature creates more UI, more behavior to test, more opportunities for bugs, and more complexity for the person using the app.
Before this project, I thought one of the difficult parts of software development was implementing everything you wanted. With AI, I started experiencing almost the opposite problem: implementation became easier, so deciding what not to build became much more important.
There were still plenty of bugs
Vibe coding definitely wasn’t a smooth path from prompt to finished application. There were lots of bugs, and some of them appeared in places I wasn’t expecting.
Sometimes a tiny change affected a completely different part of the app. Sometimes Claude misunderstood what I meant. Sometimes it implemented exactly what I requested, but the result still didn’t feel right.
And sometimes Claude wasn’t the problem at all. I would describe a feature, see it working exactly as requested, and realize that my original idea simply wasn’t very good.
That distinction became important. When AI can implement your idea quickly, you get feedback on the idea itself much sooner.
Instead of spending days building something before discovering that the UX doesn’t work, I could sometimes reach that realization within one iteration.
What vibe coding actually taught me
Before building Immerse, it was easy to imagine vibe coding as something close to a magic button: describe an app, let the AI write it, and eventually you have a finished product.
My experience was very different.
AI made implementation dramatically faster, but it didn’t remove the need for product thinking. I still had to decide how Immerse should look, which features mattered, which bugs were important, what needed to be simplified, and whether each new version was genuinely better.
In some ways, coding became a smaller part of my job while everything around the code became more important. Testing, UX decisions, prioritization, iteration, and simply having enough taste to recognize when something looked or felt wrong became a huge part of the process.
That’s what I find most interesting about vibe coding now. AI doesn’t necessarily reduce the amount of work. It changes the kind of work you spend your time doing.
What Immerse looks like today
After all those iterations, Immerse is pretty close to the focus app I originally wanted to build for myself. I deliberately kept the main interface minimal, but there’s quite a lot underneath it.
Users can choose different timer visualizations, customize minute markers, switch between themes and backgrounds, use their own photos, create different activities, explore detailed focus statistics, and block distracting apps during active sessions.
It can be used for classic Pomodoro sessions, longer deep-work blocks, studying, reading, coding, or basically anything where you want a defined period of uninterrupted focus.
And for now, Immerse is completely free.
Would I build another app this way?
Yes.
But after building Immerse, I no longer think of vibe coding as “telling AI to make an app.” I think of it more as a very fast loop between an idea and something you can actually test.
That loop changes a lot. Instead of wondering for days whether an interaction might work, I can build it and find out. Instead of trying to perfectly plan every feature in advance, I can create a small version, use it, and decide what happens next.
The technology made implementation faster, but it didn’t magically tell me what the right product should be. I still had to make those choices myself.
And that’s probably my biggest takeaway from building my first iOS app with AI:
Coding is becoming cheaper. Good product decisions aren’t.
https://apps.apple.com/tr/app/immerse-pomodoro-focus-timer/id6782882276





Top comments (0)