For two days the series went mobile-adjacent (on-device Whisper), and today it goes fully mobile: I built a real phone app — Country Explorer — with Flutter, the framework that ships one codebase to both iOS and Android. And the whole thing is three widgets in a trench coat.
This is Day 48 of TechFromZero — a new technology every day, built from scratch.
The pitch: one codebase, every platform
Flutter lets you write your UI once in Dart and ship it to iOS, Android, web, and desktop from the same code. No separate Swift and Kotlin teams. It draws every pixel itself with its own rendering engine, so the app looks and behaves identically everywhere.
flutter create country_explorer
flutter run # hot-reloads straight onto your phone or emulator
That flutter run with hot reload is the magic moment — change a line, see it on the device in under a second.
Everything is a widget
In Flutter the entire UI is a tree of widgets. The button is a widget, the padding around it is a widget, the screen is a widget. You build interfaces by nesting widgets — no XML, no storyboards. Once that clicks, the whole framework feels consistent.
Scaffold(
appBar: AppBar(title: Text('🌍 Countries')),
body: CountryList(),
)
Stateless vs Stateful + setState
A StatelessWidget just draws from its inputs (a country row). A StatefulWidget holds changing data — the search text, the loaded list. When that data changes you call setState(), and Flutter re-runs build() to repaint only what changed. That's the entire reactivity model.
setState(() => query = newText); // build() runs again with the new query
FutureBuilder for async data
Apps live on network calls. FutureBuilder takes a Future (your API request) and rebuilds itself as it resolves — spinner while waiting, list when data arrives, error if it fails. No manual loading flags:
FutureBuilder(
future: fetchCountries(), // http.get(restcountries.com)
builder: (ctx, snap) => snap.hasData
? CountryListView(snap.data!)
: CircularProgressIndicator(),
)
Country Explorer pulls real data from the free REST Countries API — no key required.
ListView.builder + Navigator
You might have 250 countries, so building every row up front is wasteful. ListView.builder is lazy — it only constructs the rows on screen and recycles them as you scroll. Tapping a row pushes a detail screen via Navigator, and the back gesture pops it, with animated transitions for free:
ListView.builder(
itemCount: countries.length,
itemBuilder: (ctx, i) => ListTile(
title: Text(countries[i].name),
onTap: () => Navigator.push(ctx,
MaterialPageRoute(builder: (_) => DetailScreen(countries[i]))),
),
)
Try it without installing Flutter
A Flutter app can't run inside a blog, so on the live page I mocked Country Explorer in a phone frame — real countries, search, tap-for-detail — so you can feel the app in your browser. The actual Dart project (the one that compiles to iOS + Android) is on GitHub.
Why Flutter took over
List + detail + navigation + async data is the skeleton of nearly every mobile app, and you've now seen all of it. Add one codebase for two platforms, sub-second hot reload, and a huge widget catalog, and you understand why so many teams reach for Flutter when they need an app on both stores without doubling the work.
👉 Try the live demo + full walkthrough: https://dev48v.infy.uk/tech/day48-flutter.html
💻 Code: https://github.com/dev48v/flutter-from-zero
🌐 All 48 days: https://dev48v.infy.uk/techfromzero.php
This is Day 48 of a 50-day series. Day 49 lands next.
Top comments (0)