I took some time off work to concentrate on learning more about Rust and possibly Phaser. But as my "study" leave was approaching, I started thinking whether it would make sense to create a game version of the number puzzle I've been writing my solving algorithm for. Soon I was wondering if I could create it as a mobile app and polish it enough to actually release it in an app store. And once I got the idea into my head, it became a goal I just couldn't forget. So once my leave started, I of course had to start with that.
Picking my poison
I decided to go with React Native as I had tried it briefly a couple of years ago in a hackathon, and its promise of producing native code for both iOS and Android is rather tempting. Also, I'm pretty familiar with React even though I'm definitely not a front-end wizard like many of my colleagues. My language choice was TypeScript, as it usually is nowadays if the other option is to go with vanilla JavaScript.
As I only have Apple hardware to test the app on, I decided to concentrate on getting the app on Apple's App Store first and then consider doing an Android version later if I still felt like it. I had had time to think about the game features etc. for a while already so I had a pretty clear backlog for those in mind when I started. There was still a lot I didn't know about React Native and especially about the process of publishing apps to App Store, so I estimated I would be able to finish the app in about three weeks (working roughly 7.5 hours on weekdays) with an additional one-week buffer for all the uncertainties and unknowns there still were.
The start was a bit slow as I mainly read about the requirements for apps on App Store and their review process. Once I felt I had a pretty good idea what was expected, I spent some time setting up the development environment. I think this took surprisingly long with my macOS having a different Ruby version built in than what React Native requires and with Xcode being involved etc. But I have to say that once I got everything set up, it was pretty impressive how I could test my emerging app with the provided iOS simulator just like I would've done with a physical device.
The good, the bad and the ugly: the code and the visuals
The actual implementation started swiftly. With the backlog items being pretty clear and small, I made nice progress and the basic game logic and a simple board UI started to be in place in a couple of days. I also stuck to writing the logic code – as well as the UI behavior, if possible – test-first, always having proper test coverage of the features from the user's point of view.
My React experience definitely helped but I still spent much of the time reading the React Native documentation, mostly learning about how it's different from web development. The styles not supporting grid layout was a bummer, but I haven't been using it for long yet anyway, so sticking with flex layouts didn't really slow me down much. Using the View
component instead of a div
element soon became second nature also.
I however realized quite early on that even though I had thought about e.g. supporting different device orientations, I hadn't thought much about supporting different appearance settings of the device; I believe I had color themes (light/dark mode) in mind already but hadn't considered e.g. font size adjustment – an important accessibility setting – at all. Realizing it can vary a lot, in addition to thinking the UI should work on tablets in addition to phones, made me spend quite some time fine-tuning the layout.
As expected, coming up with good colors for both color themes took quite a while and loads of testing in the simulator and on my actual phone that I used for testing from early on. I also spent a ridiculous amount of time trying out different fonts and reading about including e.g. Google fonts in React Native projects etc. As I had already made some technical decisions that tied me to iOS exclusively, I ended up going with one of its built-in fonts that Android devices don't have.
While I was polishing the app, I spent a lot of time trying it out with different devices and screen sizes in the simulator. I kept making changes to the layout to the very end as especially the font size setting proved to be quite a big deal as expected when trying to prevent elements from overlapping in the UI. Luckily there's a way to limit the maximum size on a per-component basis, so the UI should now stay in usable shape while also providing some support for accessibility adjustments.
Lessons learned
In the end there were quite a few things that I had absolutely no experience in when I started the project. I wanted to give the user a chance to adjust some game settings that should be persisted from a gaming session to the next, and also to store some statistics of their performance to give them some sense of advancing in the game. So I had to learn how to store data on the device, hopefully in a way that would be included in a device backup also. I wanted the app not to open any connections to the outside world, so this data isn't persisted outside the device. That simplified things a lot. On the other hand that might not be optimal for the user, as now their settings and statistics aren't shared between devices if they install the app on several ones with the same user account. Also, if they remove the app and then re-add it later from App Store, their progress is lost. This is something I might fix in possible later versions.
What's in a name?
When I finally felt like the app is getting ready – by the end of the fourth week – I still burned some hours on several days making the app ready for the App Store review. First, I made the mistake of just browsing the App Store to see if there's already an app with the name I had decided to go with. I couldn't find one, but when I made a release build, the automated validation of the archive in Xcode failed because there actually was an app (well, at least a registration of one) with the same name.
So I then had to pick another name. The name is only displayed in the app in its instructions, so changing it there took less than a minute. But I also had to recreate the app's splash screen that had the name as a logo on it. I think this was also a good thing in the end, as I had spent perhaps two days creating a 3D logo for the old name, and whenever I felt I had a good one finalized, it just looked awful on the actual splash screen. So once I had to switch the name, I just scrapped the design completely and went with a simple text component in Xcode's visual editor — a decision I'm really happy with in the end. Luckily the app icon didn't include the name, so it didn't need any changes.
Unfortunately I also wanted to rename the project workspace to reflect the new name. I had done this once already, as I started working on the project with the working title "Project X" — yes, my imagination knows no bounds — and had only just settled on a name when preparing the app for release. It turned out renaming a project isn't that simple with all the workspace files Xcode creates and builds, and of course caches somewhere also. I wasted quite a lot of time with this, and had the pleasure of having to do it twice.
The gatekeepers
After all the code is written, making one's app available on App Store is still behind a couple of hurdles.
I can only blame myself for the first one. I knew I needed to join the Apple Developer Program before I could submit my app for review. Naturally I joined only on the fourth week of development, and realized I might not get accepted immediately. Luckily my entry was processed quickly, like everything else that was said to possibly take some time. I can say I'm very happy with the speed Apple did their part in every turn, so they definitely weren't to blame for the time it took for my app to be available.
However, they are quite strict about what they allow in App Store and what information they need from the developers before an entry can be approved. I had to write a publicly available privacy policy and support contact information for the app (which I created under this domain, not realizing I could've used e.g. Github for that) instead of just listing it in App Store. I naturally also had to sign some agreements, and as my app is a paid app, fill in my banking details and tax information in a way that made me call both my bank and the tax office to get everything right.
As my app is available for both the iPhone and iPad, I also had to include screenshots of it in four different sizes. I don't think the actual measurements were mentioned anywhere until I tried to add a screenshot and got an error message saying what size is expected. And at that point I had no idea how to get screenshots in those sizes. Luckily Stack Overflow helped me once again.
All in all, I guess this process makes it harder for scammers etc. to flood App Store with harmful apps, so there's a reason for all of these. I know I got frustrated, but also, once I had filled in everything and actually got my app to review, it passed on first try, in less than 24 hours.
What's next?
I decided to make the app available without really telling anyone, just to see if someone would actually buy it without any marketing whatsoever. The result of the experiment is pretty clear: they didn't.
I know some friends will get it once I let them know about it but for now it definitely seems like I shouldn't quit my day job quite yet. I also have to see if I feel it's worth my time to develop the app any further or make that Android version available also. Even though I quite enjoyed writing the game logic, I don't look forward to making the layout work in more devices and possibly jumping through some more hoops to get it available on Google Play.