Building the Subspace Mobile App
A behind-the-scenes look at how I designed and built the Subspace mobile app using Flutter and Dart — from UI polish and API calls to image handling and layout quirks.
Building the Subspace Mobile App: A Warp-Speed Ride Through Flutter, APIs, and Android Woes
After some time wrangling ASP.NET Core APIs, fine-tuning Entity Framework migrations, and reverse-proxying through nginx like it’s a second language, I decided to tackle something new: a mobile app for Subspace. The idea was simple — take my Subspace API, which serves up random Star Trek episodes, and build a companion app that could do the same with a clean, sci-fi-flavoured UI.
Of course, nothing’s ever as simple as it sounds.
Why Flutter?
I’ve been neck-deep in .NET lately, especially with MAUI kicking around as the successor to Xamarin (RIP). But after experimenting with both, I found Flutter had the right mix of portability, visual flair, and—most importantly—momentum. MAUI still feels like it’s trying to find its feet, while Flutter just works (mostly). Plus, Dart isn’t awful. I still prefer C# as a language, but for a UI-first mobile app? Flutter wins on speed and tooling.
The First Run: The Sanity Check
Naturally, the very first project I spun up refused to run on Chrome. Errors everywhere. Turns out VS Code’s Flutter extensions were acting up. After some hair-pulling, I created a sanity_check
app and confirmed the problem wasn’t Flutter — it was my IDE. Restart, clean install, new project. Fixed. Off to a great start.
Talking to the API: CORS Strikes Again
You’d think by now I’d have CORS figured out. But when testing the app’s network calls to the Subspace API, Android laughed in my face. 403s, 404s, silence — you name it. The solution? Well for starters, I removed the CORS configuration entirely! Sure, it is perhaps good practice to always include it, but then this is a public API and it really wasn’t necessary. Remove it and the API and nginx stop fighting over who has precedence.
One final issue stood in my way, and this was born completley out of my ignorance and lack of experience with Flutter. I added the final feature to my new app and wanted to begin testing on my Android phone. I loaded it, opened it up and … nothing. Just errors. It seems that an app has to be explicitly given access to the internet, something that was fixed with one line:
1
<uses-permission android:name="android.permission.INTERNET" />
Let this be a reminder to check the damn manifest early.
Custom Fonts, Backgrounds, and Styling Shenanigans
I’m a sucker for aesthetics. Subspace had to look like Star Trek — clean, futuristic, and recognisable without being IP-infringing. That meant:
- Custom
StarTrek
font? Done. - Random rotating background images of classic scenes? Done.
- Themed buttons and cards with drop shadows and rounded edges? Done.
- Manual positioning using
Stack
,Align
, and enoughEdgeInsets
to fill a warp core? Also done.
Styling in Flutter is powerful but verbose. For anyone familiar with the old MUSH servers, it feels like softcode with curly braces, brackets and elippses everywhere. I now have deep respect for anyone building pixel-perfect designs in Flutter because it is not the most readable code I’ve ever dealt with.
Random Episode Generation
This part was a breeze. A single API call to:
1
https://api.subspaceapi.com/api/episodes/random
… and the app fetches a random episode JSON. The fun part was integrating background images, series chips, and custom UI animations without making it feel clunky. There’s now a “Generate Random Episode” button styled like it belongs on the Enterprise bridge.
Buttons, Icons, and Layouts
Early UI decisions made the app feel like a web app inside a mobile wrapper. So I scrapped the initial button placements and moved to a more intuitive layout:
- Top: Episode card.
- Bottom left: Home button with a
home
icon. - Bottom right: Refresh button with a
refresh
icon.
Simple, clean, easy to use one-handed. Looks good. Feels better. Below are a few sample screens.
App Name and Icon
Changing the app name from subspace_mobile
to just Subspace required editing the android:label
inside AndroidManifest.xml
. Adding the icon involved flutter_launcher_icons
, and yes — it does want a 512x512 PNG, not 469x469. Don’t ask me why. Just resize the image.
Flutter Web? Maybe Later.
A brief detour into running this on the web reminded me why mobile-first was the right call. The layout, performance, and API access just feel better natively. Flutter web isn’t bad, but it’s not quite there for production—yet.
What’s Next?
- Favourites
- Sharing options (because who doesn’t want to scream “Best of Both Worlds” into the void of social media?)
- Maybe even a daily notification that says “Your random episode is ready, Captain.”
- Release! Yes, I will be releasing this app onto the Android and iOS app stores. I have to finish setting up my developer accounts on both, and there are a couple little things to iron out, but I think this app is almost ready for prime time.
Final Thoughts
Building the Subspace mobile app has been one of the most fun dev projects I’ve done in years. It’s simple, purpose-built, and scratches that Trekkie itch with just enough polish to feel like something I’d actually use — because I do.
If you’re a Star Trek fan, Flutter dev, or just like watching someone dive into the deep end with style, keep an eye on this project. The next update’s coming at warp speed.
Live long and debug.