In 2020, I decided to build a mobile app from scratch. Not just an iOS app or an Android app, but something that worked seamlessly on both platforms. That project became Exchanger—a currency exchange app built with Flutter that could run on Android and iOS from a single codebase.
The concept was straightforward: a mobile app where you could check real-time exchange rates, convert between currencies, and track your conversions. Nothing revolutionary, but it was a problem space I understood, and it let me explore cross-platform development.
Plus, I wanted to build something that felt like a real app, not just a portfolio project. That meant:
At the time (2020), there were a few options for cross-platform mobile development:
I chose Flutter because:
The tradeoff was learning Dart, which wasn’t as widely used as JavaScript or C#. But Dart’s syntax is clean, and if you know JavaScript or Java, you can pick it up quickly.
Flutter’s widget-based approach took some getting used to. Everything is a widget—your layout, your UI components, even your app itself. It’s very declarative:
// Simplified example
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Exchanger')),
body: CurrencyConverter(),
);
}
The hardest part wasn’t the language or framework—it was thinking about mobile-specific concerns:
I used Flutter’s built-in state management initially, but as the app grew, I learned why people use solutions like Provider or Bloc.
The backend was built with Node.js and Express, which felt more familiar coming from web development. The API had endpoints for:
I structured the API to be clean and predictable:
GET /api/rates - Get all current rates
GET /api/rates/:currency - Get rates for specific currency
POST /api/convert - Convert between two currencies
GET /api/history/:currency - Get historical data
This was my first time designing a RESTful API from scratch (not just following a tutorial). I learned:
/api/v1/rates is better than /api/ratesI used MSSQL for storing exchange rate data and user preferences. The schema was relatively simple:
One lesson: don’t over-normalize your database if you don’t need to. I initially split everything into a ton of tables, then realized I was doing complex joins for simple queries.
Even though Flutter is cross-platform, iOS and Android still have differences:
I ended up using platform-specific widgets in some places to make the app feel native on each platform.
I was using a third-party API for exchange rates, and they had rate limits. I hit them constantly during testing.
Solution: Cache exchange rates locally and only fetch new data every 10 minutes. Most users don’t need real-time-to-the-second exchange rates anyway.
Flutter’s setState() works fine for simple apps, but once you have data flowing between multiple screens, it gets messy fast. I eventually refactored to use Provider for state management, which made the code much cleaner.
Flutter let me build for iOS and Android simultaneously, which was amazing. But I sometimes found myself fighting the framework to get platform-specific behavior.
There’s no perfect solution. Native development gives you more control but requires two codebases. Cross-platform saves time but requires compromises.
Building mobile apps taught me to think about:
On a desktop with a fast connection, a 500ms API response is fine. On mobile with spotty 4G, it’s painful. I learned to:
By the end of the project, I had:
Did it become the next big fintech app? No. Did I learn a ton? Absolutely.
Yes, especially for:
For apps that need tight OS integration or bleeding-edge platform features, I’d consider going native.
Building Exchanger taught me that finishing a project is harder than starting one. It’s easy to get 80% of the way there. It’s hard to handle edge cases, polish the UI, and actually ship something you’re proud of.
If you’re thinking about building a mobile app, pick a problem you care about (even if it’s already been solved), choose a stack, and ship something. You’ll learn more from one completed project than from ten half-finished ones.
Tech Stack: Flutter, Dart, Node.js, Express, MSSQL
Platforms: iOS & Android
Project Year: 2020
Status: Completed and deployed to test devices