Reflections on Building an iOS App in 2026
For the past couple of months I've been building an app called Autorota. Here are some thoughts I had on the process.
Working at a low-tech cafe inspired me to improve their systems a bit. I’ve written a website for them, and I’ve just finished writing an app that was made specifically for our existing management system: a very low cost management software intended to be used by a single manager to schedule people for upcoming rotas or shift schedules. My stack included MySQL, Rust, and SwiftUI, using UniFFI bridges to connect the engine with Apple’s frontend. I chose Rust because I knew the language fairly well, after having read Blandy’s Programming Rust and Gjengset’s Rust for Rustaceans, and coding up a couple small projects in the language by hand. Ultimately, I thought that using Claude to code with Rust would be a solid way to design a backend in this vibing-era of 2026. I had a feeling that upfront compile costs would be worth some friction compared to a GC in terms of performance, and I thought Cargo as an everything manager for the language would fit like a glove into AI workflows. So that turned out to be my stack.
I started doing this project around March or April. What I really enjoyed back then was getting to know Xcode and the simulator development process. Despite Xcode’s horrific performance on my laptop and having to toggle a lot of its build settings, using the simulator was and continues to be a very enjoyable process. Once I started using my actual phone as a testing device, I realized how Apple’s magic had really blended into their development interface as well.
It was fun getting to know the process of using Claude to iterate on designs as well. I learned what kind of interfaces were easy to customize, learned that between two implementation choices, the “easy way” was still most often the “right way”. Creating custom UI details in SwiftUI for example was not often worth it, unless it was a core feature. And even then, using SwiftUI’s strongest building blocks most often was the best way to build a custom component which looked good.
It was important for me to make this app feel like an Apple product. Of course, growing up with Apple products likely increased my affinity for their style, but more importantly, I believe that both Apple users and employees alike enjoy a certain level of cohesion throughout their entire ecosystem. I didn’t feel like going against the grain for this app - it’s not meant to be that kind of product. It was best for it to fit into this larger sphere of design ideology, and I think the finished product has benefited because of that ideology’s merits.
My priority when designing is always to maximize the user’s experience. Of course this necessitates design and architecture decisions across a myriad of categories, but of foremost importance is imagining the user under consideration. At the time of writing the app, along with managing some things myself, I knew the manager very well and talked with him extensively about his rota-creation processes and what he wanted from a service that offered to do that for him. I also talked to a couple more hospitality managers about the process they go through to create a rota, and how that continued after-the-fact, throughout the week. Each process was very different. Even managers using the same service, such as Deputy, had built habits of use entirely different from one another. Some managers used pen and paper, and others took more of a step back and let a service do everything for them. So how could I create a service myself that enabled each of them to still get some utility out of it? And how could I convince them to at least try the app out, when they already had invested time and money in alternatives?
What I learned was that every single one of them, despite their enormous personal differences, valued a set of software characteristics that, when done well, would lead them to at least take a look at it. Number one was an easy onboarding process. It was plain to see from the way some of them described their processes that they had a difficulty learning how to best use it, which scaled with the complexity of the software in question (this wasn’t a problem for those still on pen and paper). Some of them didn’t mind too much, such as a manager who was leading a chain of a large franchise which subscribed to a software in bulk, so there were no alternatives, and in getting a promotion came a raise, so they felt duly motivated to learn the software. It doesn’t mean that process was as pleasant as it could be, however. Another complaint that continued to be lodged was that using the software was overwhelming. There were too many options, and even if the user felt like they were acquainted with it, there was still a small mental barrier every time they wanted to use it. Another was that the design felt outdated. I could see that myself when I took a look at some of them. Many managers admitted they weren’t tech experts, but that didn’t mean they found a mid-2000s aesthetic terribly appealing (in fact, it may be quite the opposite if techies tend to find some nostalgia in that era of UI[-less] design).
So from these conversations I found a set of core design tenets emerge which would become the guidelines for how I wanted the app to look, feel, and behave. My app needed to feature a modern, approachable, and easy-to-use interface that didn’t step too far in the direction of slick, AI-powered, next-gen apps which cost more kidneys than is healthy. But it also needed to treat the user like a productive and professional adult, and shy away from dumbed-down kiddie screens that use containers whose silhouettes remind you of MEGA BLOKS (not even legos). I wanted my user to experience a most minimal mental barrier when opening the app and considering how to do a task. Sure, after a year of using some software if may come to feel like second-nature to perform its designated task. But my app didn’t have the privilege to be bought in bulk, thereby forcing managers to learn it. It needed to feel like you could master the most important tasks very quickly. This necessitated individual steps to flow together as naturally as possible, such that a user’s intuition might seize their methodology on its very own. Such that the mechanism which makes the app tick might be understood as naturally as an albatross understands shifts in the atmosphere’s currents.
The actual construction of the app would be best explained by imaginging each component of the app as a node in a tree. The app itself is the root node, and each tab contained in the app would be its children. Every component visible immediately upon opening a tab its children, so on and so forth. I used these “flows” as a baseline for my design. I wanted every node to connect logically to its destination in a natural way in regards to the overall tree structure. Some may think it an obvious approach, but as I found while building the app, there are many pitfalls that would’ve resulted in a somewhat backwards decision process - AKA bad flow. These pitfalls often appear because a blueprint that worked before, and is indeed less costly, may not work so well when reused. I’m looking at you, Panama Canal. An example in my own app was deciding how to arrange the UI for exporting the rota. The actual button where you hit “export”, and an iOS preview screen comes up. The complication is that there is the aspect of customizing how you want an export to look like, formatting it and such, and then there is that holy spot where you actually send it. On one hand, there is a certain importance to keeping the functions within each tab unified, and not allowing one function to bleed into multiple tabs. There is a certain organizational sense to this which is hard disagree with. But without question, it can disrupt flow.
I wanted the rota tab to serve as the “home base” of my app for the users to anchor themselves to. Users open up the app and they’re greeted with its definite purpose from the start. That’s where their root node is. From there they are presented with a slew of options where each node is equal to the other. The tab bar provides transit to employees, shifts, and menu, which is like the arrow at the margins of a digital map alluding to a land brimming with potential for exploration. Equal to them is every shift - a tappable container allowing the user to change things up then and there. In the top right corner is the sandbox button, which, when toggled on, transforms rota’s topography into one streamlined for bulk editing. Quick, rapid-fire changes are made in one or two taps en-masse here. Lastly, the top left (the least accessible corner for righties), , is where I placed what I thought the most marginal options to rota’s function would be. This is where the main export button is, and not the export tab, which is simply left for configuration. Even though it doesn’t neatly fit organizational perfection, it enhances the user flow, and actually fits the energy and momentum rota’s tab carries. It takes three taps to export a rota from the rota page on iPhone, and only two on the iPad.
So too have I been swept up by some kind of momentum in these past couple of paragraphs - not necessarily a good thing! My app has been under review for about a week now, so as it pushes through the review process, I’ll continue to write some of my reflections on building the app. I realise that I’ve spent most of my allowance here on UI/UX and my design process, but I want to write about the ever imminent, ever terrifying vibe coding next, and how I’ve grappled with its growing presence, and how I’ve utilised it in this app. It was a recent New York Times article on the booming number of apps being published on the app store, and some of the people behind them, one of whom is from my home city of Chicago! But I’ll leave it until then.