Ship One Codebase to iOS, Android & Web
A from-zero mobile path built around Dart and Flutter — widgets and layout, navigation, state management, networking, native device APIs and platform channels, testing and app store publishing, ending with a capstone app you actually ship to real devices. All 20 weeks are live, start to finish.
Prerequisites & tooling
What you should already know
- Basic programming fundamentals — variables, loops, functions, simple object-oriented concepts, in any language
- Comfortable with the command line, and basic Git (this site's Git & GitHub course covers everything needed)
- No prior Dart, Flutter, or mobile development experience required — Dart is taught from scratch starting Week 1
- A machine with 8GB+ RAM; a Mac is only required later for building/testing on iOS specifically
Stack you'll work with
One codebase, one language, compiled to genuinely native output on every target platform.
The full 20-week roadmap
Eight phases, from your first Flutter app through state management and native device APIs, to a published app on the store. All 20 weeks are live below.
Dart Fundamentals & Your First Flutter App
Learn the language Flutter is built on, then get a real app running on a device or simulator.
- Dart syntax, null safety, functions & classes
- Installing the Flutter SDK &
flutter doctor flutter create, project structure & hot reload
Widgets, Layout & Styling
Learn the primitives every Flutter screen is built from — everything is a widget.
- StatelessWidget vs. StatefulWidget & the widget tree
Row,Column,Stack,Container& constraint-based layout- Styling with
ThemeData& why there's no CSS
Material Design, Theming & Responsive Layouts
Turn a plain screen into a properly styled, adaptive app.
- Material 3 components:
Scaffold,AppBar,Card,ListTile - Light/dark theming with
ColorScheme.fromSeed MediaQuery,LayoutBuilder& adaptive layouts for tablets/web
Navigation Basics — Navigator & Named Routes
Move between screens the way a real app does.
Navigator.push/pop& passing data between screens- Named routes & a centralized route table
- Bottom navigation bars & tab-based layouts
go_router, Nested Navigation & Deep Linking
Compose complex, URL-driven navigation the way production apps need.
- Declarative routing with
go_router - Nested navigators & shell routes for tab flows
- Deep links & auth-gated redirects
State Management I — setState, InheritedWidget & ValueNotifier
Understand what Flutter's state management libraries are actually built on top of.
setState& why it doesn't scale past a single widgetInheritedWidget& how data flows down the widget treeValueNotifier&ChangeNotifieras the building blocks underneath
Provider for App-Wide State
Reach for a real state management library once an app outgrows one screen.
- Expose a
ChangeNotifierto the widget tree withChangeNotifierProvider - Consume provided state with
Consumer, and understand the difference fromcontext.watch/context.read - Organize multiple providers with
MultiProvider
Riverpod: Providers, Notifiers & Compile-Time Safety
Trade Provider's context dependency for compile-time safety and easy testing.
- Define and read providers with Riverpod, without needing a
BuildContext - Model mutable state with a
Notifierand understand what compile-time safety Riverpod adds over Provider - Test provider logic in isolation, without building any widget tree
REST Networking with http/dio & JSON
Connect the app to a real backend and manage server state.
- Make a GET and POST request with the
httppackage - Serialize and deserialize JSON into typed Dart classes
- Use
diofor interceptors, timeouts, and richer error handling
Local Persistence & Offline-First Patterns
Cache data on-device and keep the app usable with no connection.
- Store and query structured data on-device with sqflite
- Store simple key-value and object data with Hive
- Choose between sqflite and Hive for a given kind of data
Camera, Media & the File System
Capture and manage photos, media and files on-device.
- Request camera permission and capture a photo with the
camerapackage - Let a user pick an existing photo with
image_picker - Read, write and locate files with
path_provideranddart:io
Location, Sensors & Permissions
Read live location and motion data, with permissions done right.
- Read a device's current location, and watch it update over time, with geolocator
- Read accelerometer data with sensors_plus
- Request location permission with a clear rationale, and distinguish "while using the app" from "always" permission
Platform Channels — Calling Native Kotlin/Swift from Dart
Bridge into real native Kotlin/Swift code when nothing else fits.
- Understand what a platform channel is, and when writing one is actually the right call
- Implement a method channel handler in Kotlin for Android
- Implement the same method channel in Swift for iOS
Implicit & Explicit Animations
Make state changes feel considered instead of abrupt.
- Animate a property change with an implicit animation widget like
AnimatedContainer - Fade a widget in and out with
AnimatedOpacity - Build a custom animation with
AnimationControllerand aTween
Custom Painting & Slivers for Advanced UI
Draw what no widget composition can, and build real scroll effects.
- Draw custom graphics with
CustomPainterand aCanvas - Understand when
shouldRepaintmatters for performance - Build a collapsing app bar with slivers and
CustomScrollView
Unit & Widget Testing with flutter_test
Build a real safety net for widgets, logic and async code.
- Write a unit test for plain Dart logic, independent of any widget
- Write a widget test using
testWidgets,pumpWidget, and finders - Simulate user interaction in a widget test and assert on the result
Integration Testing with integration_test
Drive the real, installed app the way a user would.
- Set up integration_test and run a test against a real device or emulator
- Write an end-to-end flow driving multiple screens
- Use
pumpAndSettlecorrectly for animated and asynchronous UI
Performance: ListView Virtualization, Rebuild Profiling & DevTools
Make the app fast under real, long-list, real-device conditions.
- Explain why
ListView.builderscales to long lists where a plainListViewdoes not - Profile unnecessary widget rebuilds with Flutter DevTools
- Apply
constconstructors and targeted rebuilds to reduce wasted work
App Signing, Build Flavors & CI/CD
Hand building and signing off to a real release pipeline.
- Sign an Android release build with a real upload keystore
- Configure an iOS release build's signing through Xcode
- Set up build flavors for development, staging, and production
Capstone — Store Submission & Ship
Get a real, signed build in front of real reviewers on both stores.
- Prepare a complete App Store Connect and Google Play Console listing
- Submit a signed production build to each store's testing track
- Recognize the most common first-submission rejection reasons on each store