Welcome back to my multi-part series on how I built a fully capable and advanced train tracking app from scratch, what I learned along the way and the challenges I faced all while I was just 14 years old when I started. In this article, I will cover how I built the original Trainly app and the differences between then and now.
What was the first prototype version like?
After I'd spent a few weeks playing around with the Live Departure Board data and time interpolation, I figured it would be much more ideal to use this technology through an app rather than a primitive terminal app. I didn't know anything about mobile development at the time, however I stumbled across a library called AndroidJS.
The AndroidJS Discovery
It basically lets you build Android apps using HTML, CSS, and JavaScript I was already familiar with. Perfect!
The Reality Check
The first prototype was rough. Really rough. Think basic webpage squashed into a phone screen, wrapped up and launched like an app.
But it worked! 🎉
- âś“ See trains from chosen station
- âś“ Live estimates
- âś“ Track progress using interpolation
"That alone made it feel magical. I could open the app, click 'Track This Train', and see something I built tell me where a train was. For the first time, I knew that I was onto something. But this also made me question the lack of similar features in existing apps."
The Obvious Limitations
But as a first attempt, it gave me the motivation to keep going.
How did I rewrite the app?
The AndroidJS Reality Check
I quickly realised that AndroidJS wasn't going to cut it long term:
- Minimal support
- Slow performance
- Library not actively maintained
The Decision
After a few weeks of battling JavaScript workarounds, I decided to rewrite the entire thing using proper Android tools.
The New Approach
Mixing HTML with Kotlin using the built-in WebView. This gave me more control and performance while still letting me use my existing front-end code.
The Improvements
The Game Changer
What really stood out to me during this phase was how much more responsive the app felt. It still had the same backend logic—interpolating between station times—but now it actually felt usable.
This rewrite gave me the confidence to show it to friends and even use it daily on my commute, trusting it over well-established apps.
What about iOS?
Of course, I couldn't leave iPhone users behind—especially since most of the people I knew used iPhones. That made it the obvious next step.
The Success
Once the Android version was working smoothly enough and published on the Play Store, I started working on an iOS version.
The Roadblock
However I hit a bit of a road block: to compile for iOS and to publish on the App Store, you require an account to be enrolled in the Apple Developer Program.
The Cost Dilemma
$99 a year (~ÂŁ70) which isn't a small amount for something I didn't even know would be worth it.
After a while though, I decided to take the plunge and spent my Christmas money on a subscription to the program.
The Implementation
At this point, I didn't want to write a completely separate frontend, so I used the same idea: embed a web interface using Swift's WebView and link it up to native features where needed.
The iOS Milestones
TestFlight Deployment
I even managed to deploy a test version using TestFlight, which made sharing the app with friends on iPhones super easy.
App Store Release
I also released this version on the App Store, which was a huge milestone for me.
Cross-Platform Achievement
More importantly, I'd officially crossed into the world of cross-platform development.
Why did I rewrite it again?
Everything changed when I discovered Flutter
Suddenly, I could build for Android and iOS at the same time—with proper native performance, beautiful UIs, and no hacky WebViews.
The Complete Transformation
I rewrote the entire app from scratch once more, making a few design tweaks, and this time it finally felt like the polished, proper experience I'd always wanted Trainly to be.
New Design Features (as it is today)
The Flutter Advantages
Single Codebase
Flutter allowed me to improve how the app handled updates. Since it's all one codebase, adding new features or fixing bugs didn't require twice the effort.
Better Focus
With more experience under my belt, I could focus on making the app faster, more stable, and more delightful to use.
It was miles ahead of the original prototype, and now something I was genuinely proud to share.
Ready to see the evolution continue? Stay tuned for Part 3 where I'll share the story of my first app release and the lessons learned!