Building Games for All Platforms
6 October 2025
There are a lot of app platforms out there, and providing quality children's games for all of them is no small feat.
We could start a debate about which is the best gaming platform - Android, iOS, Windows, macOS - but we'll never get everyone to agree.
Everybody has their own preferences for which type of devices they want to have, and as a game development company, we really don't have an opinion on which is the best. Instead, we build our games for all platforms.
It wasn't always this way. For the first year, we built our games just for Android, because that was the platform we were most familiar with. Building on Android first taught us a lot about how people play our games, but we pretty quickly realized that if we wanted to reach the largest audience, we needed to support other platforms as well.
As developers, the moment we started to research our options for deploying our games on different platforms was the moment we realized that we should have tackled this problem from the beginning.
Android games are, by default, built in Java (or these days Kotlin, which shares a lot of heritage with Java), but Java doesn't work well on the other platforms. Despite having decades of opportunities to be adopted by all the different platforms, it just never happened.
This meant we had invested an entire year in developing three games in Java, but wouldn't be able to deploy those games to any platform other than Android. Bummer.
After looking at a lot of different options, we decided to go with Dart and Flutter. Honestly, the decision wasn't very clear at first, and we weren't sure it would ultimately be the correct path forward.
The decision to go multi-platform roughly coincided with winter holiday in Sweden: the darkest, coldest months of the year when we like to hibernate in our house, and when we had several weeks that we could concentrate on the task of migrating our code from Java to Flutter. It seemed like an insurmountable task before we got started, but once we started writing code, we were very pleasantly surprised.
In just a little under four weeks, we had converted around 92,000 lines of Java code to Dart and had the bulk of the functionality up and running on Android and iOS devices.
Now, getting the software working on both platforms is one thing, but working out all the build pipeline plumbing was something else entirely.
We wound up spending countless hours trying to figure out the magic incantations for how to get things to work, especially for iOS deployments. Apple seems to have taken a particular liking to making developer's lives miserable, and the whole process felt incredibly fragile. Indeed, there were several times when the build pipeline was working correctly and then broke for no discernible reason, and required hours of additional tinkering to fix.
Even once those particular kinks were worked out, we had to repeat that process for macOS builds.
Building for Windows also turned out to be non-trivial, although thankfully Microsoft is a much more developer-friendly company, and aside from a few Azure AD mishaps, we were mostly up and running pretty quickly.
Creating automated build pipelines for multiple apps to be deployed across multiple platforms is a daunting task. We have a total of five games in our pipeline right now (yes, we only have three published at the moment, but two others are well under way).
We build each app for a total of four main platforms (Android, iOS, macOS, and Windows), with additional builds for Linux and the web being perfected as well.
Doing some quick back-of-the-napkin math, that means that every time we go to do a deployment, we have to run a total of 30 different build processes, and hope that none of them break.
This is a non-trivial amount of complexity, and one which still gives us a bit of heartburn occasionally.
But the good news is that we've got a fairly stable build environment that has been implemented using GitHub Actions, and which is now successful the vast majority of the time. The total build cycle from start to finish takes about 45 minutes, but that's not too shabby, and there are some additional opportunities for parallelization that we can take advantage of to shorten that time up a bit more.
Going forward, especially as we add more game titles to our library, this process will continue to grow in complexity. But now that we have a pretty stable blueprint for adding more apps, we don't anticipate many more problems going forward.
Famous last words, I suppose...
