Beginner to intermediate · 24 hours · 223 lessons · English, with captions
The Complete Flutter Course: Build Android, iOS and Web Apps
The complete Flutter SDK, Flutter framework, Dart and Firebase course to develop fast, production-grade apps for Android, iOS and the web.
-
Sagnik Bhattacharya 30,000 students from 175 countries -
Paulina Knop Flutter developer and curriculum designer
What you will learn
By the end, you will be able to:
- Write Dart with confidence and understand how Flutter builds a user interface from widgets.
- Use more than 150 Flutter widgets and create your own custom UI components.
- Build responsive layouts and animations that run on Android, iOS and the web from one codebase.
- Handle asynchronous work with Futures and Streams so the interface stays smooth while data loads.
- Manage state with Riverpod and apply design patterns such as MVVM so an app stays maintainable as it grows.
- Connect to REST APIs and Firebase for authentication, data and storage.
- Handle navigation with named routes, pass data between pages and keep web addresses clean.
- Set up continuous integration with GitHub Actions so every push builds your app automatically.
- Finish nine real apps you can show in interviews and on your portfolio.
-
Sagnik Bhattacharya
30,000 students from 175 countries
-
Paulina Knop
Flutter developer and curriculum designer
Curriculum
Every lesson, in order.
25 sections · 223 lessons · 24 hours
01 Introduction
You see what Flutter is and why one codebase for Android, iOS, web and desktop saves you rebuilding the same app for each platform, then watch a small coffee-counter app come together widget by widget. You also look under the hood at how Dart is compiled to native code and how Flutter draws the screen with its own rendering engine.
- 1 What is Flutter? One codebase for Android, iOS, web and desktop apps 5 min
- 2 A coffee counter app, widget by widget AppBar, buttons, setState and the same code on the web 5 min
- 3 How Flutter works under the hood Dart, native compilation and the Flutter rendering engine 5 min
02 Flutter Setup and Installation
You set up Flutter on Windows or a Mac: Java, Git, the Flutter SDK and Android Studio with its Flutter and Dart plugins, then an Android emulator or your own phone with USB debugging. You fix the issues flutter doctor (Flutter's built-in set-up check) reports, install the Firebase command-line tools and, if you want them, add Visual Studio for Windows desktop apps or Xcode for the iOS Simulator.
- 4 Install Java on Windows System requirements, JDK, JAVA_HOME and the Path variable 4 min
- 5 Install Git on Windows The 64-bit installer with the default settings 1 min
- 6 Install Flutter on Windows Download and extract the SDK, then add it to the Path 3 min
- 7 Install Android Studio on Windows Flutter and Dart plugins, SDK tools and format on save 7 min
- 8 Set up an Android emulator or your phone Virtual device, x86_64 image, Hyper-V and USB debugging 7 min
- 9 Run flutter doctor and accept Android licences Read the report and run flutter doctor --android-licenses 1 min
- 10 Install the Firebase CLI on Windows Node.js and npm, then npm install -g firebase-tools 3 min
- 11 Optional: set up Windows desktop apps Visual Studio, NuGet, flutter config and Developer Mode 4 min
- 12 Complete Flutter set-up on a Mac Java, the SDK, Android Studio, emulator, Xcode and Node.js 7 min
03 My Dashatar app - Start with the basics to create your First Flutter App
You build your first app, My Dashatar, which shows your own version of Dash, the Flutter and Dart mascot. You create and organise a project in Android Studio, build a widget tree with MaterialApp, Scaffold, AppBar, Center and Image, add an image through pubspec.yaml and meet Dart's basic data types. You finish by giving the app its own launcher icon on Android, iOS and the web, and by fixing a common Gradle build error.
Code on GitHub: My Dashatar app
- 13 Meet Dash and create the My Dashatar project Project name, workspace folder and organisation domain 5 min
- 14 Build your first widget tree MaterialApp, Center and Text, plus web support and Alt+Enter 7 min
- 15 Make your Dashatar and add an AppBar Scaffold, centred title, hex colours and Dart data types 7 min
- 16 Add your Dashatar image to the app Assets in pubspec.yaml, Image.asset and the debug banner 8 min
- 17 Change the launcher icon: new manual method Copy generated icon files into Android, iOS and web folders 8 min
- 18 Change the launcher icon: older package method The flutter_launcher_icons package and dev_dependencies 6 min
- 19 Fix build errors by upgrading Gradle Android Studio upgrade assistant, flutter clean and pub get 2 min
04 Ninja Challenge 1
Your first Ninja Challenge: build an app like My Dashatar on your own, but load the picture straight from the internet instead of storing it in the project. The solution builds a coffee app with Image.network, then restyles the AppBar title, removes its shadow and adjusts the colours and font size.
- 20 Ninja Challenge 1: load an online image Build an app like My Dashatar without storing the picture 2 min
- 21 Ninja Challenge 1 solution: a coffee app Image.network, then AppBar elevation, colours and font size 7 min
05 My Dashatar App - Understanding Flutter layouts in depth
Back in My Dashatar, you turn the app into a stateless widget and see how hot reload shows your changes almost instantly. You arrange containers with Column and Row, align them along both axes, inspect them with the Flutter Inspector and fix overflow errors with ListView and SingleChildScrollView, then use Wrap to flow widgets onto the next line and Stack with Positioned to layer one widget over another.
- 22 Turn My Dashatar into a stateless widget Emulator Quick Boot, a MyApp class and the stless shortcut 5 min
- 23 Hot reload vs hot restart What each reloads, then size an image with a Container 4 min
- 24 Lists in Dart and the Column widget Typed lists in DartPad and a Column of coloured containers 5 min
- 25 Align widgets in a Row and a Column Main and cross axis alignment and the Flutter Inspector 7 min
- 26 ListView and SingleChildScrollView Fix overflow errors with vertical and horizontal scrolling 5 min
- 27 Wrap, Stack and Positioned widgets Flow widgets onto the next line and layer one over another 5 min
06 Dart Programming
In DartPad, an editor for Dart that runs in your browser, you learn the Dart the rest of the course relies on by building an even-number checker: classes and objects, methods and return values, constructors, if and else, and the modulo operator. You then work with loops, lists, maps and string methods, and test yourself with two sets of challenges, such as summing every number from 100 to 1,000 or finding the largest of three numbers.
- 28 Classes, objects and "Hello World" A class with a method, void main and an object in DartPad 3 min
- 29 Access a class variable through an object Declare int a in the class and print obj.a 0 min
- 30 Methods that return a value Return types, the return keyword and storing the result 1 min
- 31 Constructors Pass a value into a new object with this.a 2 min
- 32 Call a method inside the constructor Run printText when the object is created and print its value 1 min
- 33 Check for even numbers The modulo operator, if, else if and a bool return type 4 min
- 34 For loops and lists in Dart Print even numbers from 1 to 10 and every item in a list 4 min
- 35 Maps in Dart Create a map, add a key and print each pair with forEach 2 min
- 36 Dart challenges, set 1 Loops, arithmetic, toString and swapping two variables 7 min
- 37 Dart challenges, set 2 Largest of three, string methods, vowels and odd numbers 6 min
07 State management - Basics
You learn what state is, turn My Dashatar into a stateful widget and use setState so each tap on Dash updates a counter and switches the background to a random colour picked with Dart's Random class. Then you add the audioplayers package so every tap plays a beat, with an AppBar button that picks a different sound.
Code on GitHub: State management starting project
- 38 Stateful vs stateless widgets What state is, then a tap counter on Dash with setState 5 min
- 39 Random background colours with setState Swap colours on tap, then pick from a list with Random 7 min
- 40 Add sound files and the audioplayers package Assets in pubspec.yaml, pub.dev checks and an AudioPlayer 4 min
- 41 Playing the beats Play on each tap and pick a random beat with an IconButton 4 min
08 Ninja challenge 2 - Launchpad app
Your second Ninja Challenge: starting from a project you clone from GitHub, build a launchpad whose pads play a sound and flash white when tapped. The solution builds one reusable stateful pad widget with a radial gradient, rounded corners and a shadow, times the flash with async and Future.delayed, and sizes the pads with MediaQuery so they fit any screen.
Code on GitHub: Launch Pad starting project Launch Pad complete app
- 42 Ninja Challenge 2: build a launchpad app Clone the starter from GitHub, colour codes and hints 6 min
- 43 Ninja Challenge 2 solution: the Pad widget Google Fonts in the AppBar, a stateful Pad and initState 7 min
- 44 Ninja Challenge 2 solution: decorate the pad Radial gradient, rounded corners, shadow and GestureDetector 5 min
- 45 Ninja Challenge 2 solution: delay and audio Half-second flash with Future.delayed and player.play 2 min
- 46 Ninja Challenge 2 solution: fit every screen Wrap spacing, MediaQuery, SafeArea, sounds and the app name 7 min
09 Layouts, Gesture and animations: Landing Page Web (Portfolio)
You start building your portfolio website with the web version of its landing page. After setting up icons, a favicon and a switch between web and mobile layouts, you build navigation tabs that animate on hover, a profile picture, reusable text widgets, cards that slide with AnimationController and a contact form, learning regular expressions, input formatters and validators along the way. You then add SVG social media icons with url_launcher links, publish the site on Firebase Hosting and learn async and await.
Code on GitHub: Portfolio app (complete)
- 47 Creating a new Flutter project Portfolio app for Android, iOS and web, and an assets folder 6 min
- 48 Changing Flutter app icons By hand, with appicon.co icons in the Android and iOS folders 4 min
- 49 Customising the Android icon with Image Asset Resize your photo and add a background colour layer 5 min
- 50 Adding a favicon for the web A favicon.io icon in the web folder and a circle-cropped photo 6 min
- 51 Project structure and LayoutBuilder Google Fonts, assets, web and mobile folders and main.dart 6 min
- 52 Layout by screen width and lint rules Web layout above 800 pixels, analysis_options.yaml and TabsWeb 6 min
- 53 When to use const or final Compile time vs runtime, and styling the tab text in Oswald 6 min
- 54 Hover effects with MouseRegion Animated tab underlines, ternary operators and Spacer 23 min
- 55 Theme colour and a full-height first section A teal accent photo ring and MediaQuery to size the section 6 min
- 56 Speech bubble greeting with BoxDecoration BorderRadius.only corners and symmetric EdgeInsets padding 6 min
- 57 Reusable SansBold and Sans text widgets Stateless widgets that take the text and font size 5 min
- 58 Contact details Your role, then email, phone and location rows with icons
- 59 About section of the web landing page Introduction text, bordered skill tags and a side image 9 min
- 60 What I do section with Card widgets A row of cards with images, and a look inside Card 5 min
- 61 Decorating the card Card title, elevation, a teal accent shadow and padding 4 min
- 62 Adding more cards App and back-end cards, BoxFit.contain and full-stack basics 4 min
- 63 Starting the contact form A Contact me heading and a TextFormField with a teal outline 6 min
- 64 Borders and hint text for a TextFormField Rounded focused border, Poppins hint text and a field heading 6 min
- 65 Turning the form field into a TextForm widget Named and required parameters and maxLines for taller fields 8 min
- 66 Laying out the contact form Name, email, phone and message fields from TextForm 7 min
- 67 Regular expression basics in Dart RegExp, hasMatch and character ranges tested in DartPad 9 min
- 68 Input formatters with RegExp FilteringTextInputFormatter and a 10-character length limit 5 min
- 69 Validating a form field with RegExp Error borders, autovalidateMode and renaming via Refactor 7 min
- 70 Doubles instead of integers and a submit button Fix int values and style a teal MaterialButton for the form 6 min
- 71 Card borders and an animated card widget Teal accent borders and parameters for AnimatedCardWeb 7 min
- 72 AnimationController and Tween Offset tweens, vsync and a four-second duration for the cards 4 min
- 73 Sliding cards with SlideTransition Cards that glide up and down with repeat(reverse: true) 6 min
- 74 Getting ready for Firebase Hosting A width-based image height and signing in with firebase login 5 min
- 75 Creating a Firebase project for hosting The console project, firebase init and flutter build web 5 min
- 76 First deploy to Firebase Hosting The firebase deploy command, release history and the drawer 6 min
- 77 SVG icons with flutter_svg Drawer name and a sharp Instagram icon with SvgPicture.asset 9 min
- 78 Opening links with url_launcher An Instagram icon button and a reusable link function 7 min
- 79 Social links and font size hierarchy Twitter and GitHub links, smaller tab text and format on save 5 min
- 80 Asynchronous code with async and await Future.delayed in DartPad and what happens without await 7 min
- 81 When to use await Timing delayed futures and when later code needs the result 5 min
10 Navigation in Flutter
Using a small test project, you learn three ways to move between pages: Navigator.push and pop, named routes, and onGenerateRoute in a routes class of its own. With the last one you pass data to a page, send unknown addresses to an error page, show the web or mobile layout by screen width and remove the # from web addresses.
Code on GitHub: Navigation starting project Navigation complete project
- 82 Navigator.push and Navigator.pop Move between two test pages with MaterialPageRoute 7 min
- 83 Named routes in MaterialApp A routes map with names for the home and about pages 4 min
- 84 Navigating with pushNamed and initialRoute Route names in the address bar and a value passed to a page 7 min
- 85 A routes class with onGenerateRoute A switch on RouteSettings in a routes file of its own 9 min
- 86 Route arguments, an error page and clean URLs Pass data, remove the # and choose a layout by screen width 16 min
11 Mobile Landing Page - Flutter Portfolio
You build the mobile landing page of the portfolio and a routes file that shows the web or mobile layout depending on screen width. The phone layout gets a right-hand drawer with navigation buttons and social media icons, an intro with your photo and contact details, skill tags, the animated cards resized for phones and a contact form, and you then link every tab to its page on both layouts.
Code on GitHub: Portfolio app (complete)
- 87 Responsive routes for the portfolio Web or mobile by width, a home fallback and url_strategy 6 min
- 88 Mobile AppBar and a right-hand drawer Transparent AppBar, endDrawer and the debug banner removed 5 min
- 89 Mobile drawer header with your photo DrawerHeader and a BoxShape.circle border on the photo 5 min
- 90 Navigation buttons in the mobile drawer A TabsMobile widget for Home, Works, Blog, About and Contact 6 min
- 91 Social media buttons in the mobile drawer Three SVG social icons that open links with url_launcher 4 min
- 92 Profile photo on the mobile landing page A ListView body and a CircleAvatar with a teal accent ring 2 min
- 93 Greeting, name and contact icons on mobile A speech bubble greeting and a vertical Wrap of icons 5 min
- 94 Mobile contact details and About me heading A Wrap of contact text and extendBodyBehindAppBar 5 min
- 95 About section of the mobile landing page Intro text and skill tags from a tealContainer function 6 min
- 96 What I do cards on mobile Optional width and height on the renamed AnimatedCard 7 min
- 97 Contact section The last animated cards and a contact form spaced with Wrap 10 min
- 98 Linking the tabs to their pages Each tab calls pushNamed, with a GestureDetector on TabsWeb 4 min
12 Contact Page - (Flutter Portfolio)
You build the portfolio's contact page in web and mobile versions and add its route. Both use a NestedScrollView with a SliverAppBar whose large header image collapses as you scroll, the navigation from the landing page and a contact form built from your reusable form widget.
Code on GitHub: Portfolio app (complete)
- 99 Starting the Contact page A /contact route by width and a drawer with social links 10 min
- 100 Collapsing header on the web Contact page NestedScrollView, SliverAppBar and a FlexibleSpaceBar image 5 min
- 101 Navigation tabs on the web Contact page TabsWeb links in the SliverAppBar and the image filter quality 5 min
- 102 The HTML web renderer, now removed The --web-renderer html flag, its hover bug and a run setup 6 min
- 103 Adding the form to the web Contact page TextForm fields for name, email, phone and message 5 min
- 104 Starting the mobile Contact page Submit button for the web form, then a drawer and SliverAppBar 6 min
- 105 Collapsing header on the mobile Contact page FlexibleSpaceBar image, then the form's Wrap and first field
- 106 Finishing the mobile contact form Remaining TextForm fields and a teal accent submit button 4 min
13 About Page - Flutter Portfolio
You build the portfolio's About page in mobile and web versions and add its route, which picks the layout by screen width. Each version opens with your photo in a round frame, a short introduction and teal skill tags, then web development, app development and back-end development sections, each pairing an animated card with a heading and a short description. Along the way you set FilterQuality.high so scaled images stay sharp, make the animated card's text optional and re-align the mobile landing page to the left.
Code on GitHub: Portfolio app (complete)
- 107 Set up the About page and its route Mobile AppBar and drawer, and a left-aligned landing page 7 min
- 108 About page introduction on mobile Nested CircleAvatars for the photo, and FilterQuality.high 5 min
- 109 Web and app development sections on mobile Animated cards with headings; the card's text made optional 6 min
- 110 Finish the mobile About page, start the web one Back-end section, then the web AppBar, drawer and social links 6 min
- 111 About page introduction on the web Greeting text, teal skill tags and a round profile photo 6 min
- 112 Ending the About page Web version: web, app and back-end development sections 9 min
14 Blog and Works Page - Flutter Portfolio
You add the Blog and Works pages in mobile and web versions, each with its own route. The blog's collapsing SliverAppBar header shows a large image and a title in AbelCustom, a new reusable text widget in the Abel font with optional colour and weight. Placeholder posts use a reusable BlogPost widget: a bordered card whose text is cut to three lines, ending in three dots, until a button expands it. The Works page showcases a project with a screenshot on an animated card, its name and a description.
Code on GitHub: Portfolio app (complete)
- 113 Start the Blog page: route, drawer and header NestedScrollView with a SliverAppBar and FlexibleSpaceBar 5 min
- 114 Build a reusable text widget in the Abel font Optional colour and weight, for the blog's header title 5 min
- 115 Finish the blog header, start BlogPost Header image with BoxFit.cover, and a bool to expand posts 5 min
- 116 Blog post headline and expand button An IconButton that flips the expand bool with setState 4 min
- 117 Blog post body text that expands Open Sans text; maxLines shows three lines or the whole post 3 min
- 118 Finish the blog post card TextOverflow.ellipsis, a solid border and more sample posts 3 min
- 119 Web version of the Blog page Copy the mobile code, left-align the title, widen the spacing 3 min
- 120 Start the Works page: route and header WorksWeb copies the Contact page's SliverAppBar and drawer 5 min
- 121 Showcasing apps Web layout: project screenshot, name and description in a row 6 min
- 122 Mobile version of the Works page SliverAppBar copied from Contact, then the project card 6 min
15 Flutter Firebase setup for Android, iOS, and web
You connect the portfolio to Firebase, Google's back-end platform for apps. The recommended way is the FlutterFire CLI (command-line tool): you create a Firebase project and a Cloud Firestore database in test mode (open to anyone for a limited time), run flutterfire configure for Android, iOS and the web, and initialise Firebase at start-up. Later lessons show the older manual set-up it replaces: registering each platform with Firebase, adding its configuration files and using kIsWeb, which is true in a browser.
Code on GitHub: Portfolio app (complete)
- 123 Connect Firebase with the FlutterFire CLI Current method: flutterfire configure for Android, iOS and web 9 min
- 124 Older manual set-up: iOS and Android apps Bundle ID, package name and each platform's configuration file 6 min
- 125 Older manual set-up: initialise Firebase Gradle settings, cloud_firestore, async main and kIsWeb 6 min
- 126 Older manual set-up: the web app Web config values in FirebaseOptions, tested on web and phone 5 min
16 Read data from Firebase using Flutter: Blog Page
You store the blog's articles in Cloud Firestore, Firebase's cloud database, as documents with a title and a body, and see why it is chosen over the Realtime Database. You read the articles once with get, then switch to a stream, a live feed that delivers new data whenever the database changes. A StreamBuilder turns each update into posts with ListView.builder and shows a loading spinner until data arrives, so articles you add or delete in the Firebase console show up on the blog straight away.
Code on GitHub: Portfolio app (complete)
- 127 Introduction to Cloud Firestore Create an articles collection with title and body fields 6 min
- 128 Read Firestore data once with get() QuerySnapshot, docs.forEach and a call from initState 5 min
- 129 Why the blog needs streams A one-off get() misses new articles; streams push changes 5 min
- 130 Stream articles from Firestore Live updates via snapshots(), and title and body for BlogPost 7 min
- 131 ListView.builder and StreamBuilder Build posts from a list, then from live Firestore snapshots 6 min
- 132 Show Firestore articles on web and mobile Each document's title and body in BlogPost, updating live 5 min
17 Add data to Firestore using Flutter: Contact page: Flutter Portfolio
You make the contact forms work. Text-editing controllers read each field, validators (checks that return an error message) make first name, email and message required, and a Form widget with a global key, an identifier the Submit button uses, checks every field at once. Submit then saves each message to a messages collection in Cloud Firestore, clears the form and confirms with a dialog. You also swap print for the logger package, which stays silent in the released app, and deploy the site to Firebase Hosting.
Code on GitHub: Portfolio app (complete)
- 133 Replace print with the logger package Keep test output out of the released app with logger.d 5 min
- 134 Read form fields with TextEditingController One controller per contact field, checked with logger.d 6 min
- 135 Required fields with validators Error messages, a Form widget and a GlobalKey to check them 7 min
- 136 Save contact messages to Firestore An addResponse function that adds to a messages collection 9 min
- 137 A submit dialog for every contact form Reset the form and show an AlertDialog from a shared function 7 min
- 138 Deploy to Firebase Hosting (HTML renderer) Run firebase init and deploy; the HTML renderer is now removed 4 min
18 Firebase security rules
You protect the database with Firestore security rules, checks on Firebase's servers that decide who may read or write each collection. Using match statements to pick the documents a rule covers, you let the app write messages but never read them and read articles but never change them, testing each rule by switching access off. The contact form then reports whether a message was saved. An optional lesson connects your own domain to Firebase Hosting with an A record, the setting that points a domain at a server.
Code on GitHub: Portfolio app (complete)
- 139 Introduction to Firestore security rules The Rules tab, test mode's time limit and allow true or false 7 min
- 140 Security rules for contact messages A match statement that lets the app write messages, not read 4 min
- 141 Article rules and fixing the submit dialog Read-only articles; addResponse now returns true or false 11 min
- 142 Connect a custom domain (optional) Point a domain you own at Firebase Hosting with an A record 5 min
19 How to reuse code in your Flutter app? (Portfolio app)
You refactor the portfolio so code is written once and reused; the earlier sections repeated it on purpose so you could practise. The web navigation tabs and drawer, the mobile drawer with its link buttons, the web and mobile contact forms and the teal skill tags become shared widgets or functions, and the two blog pages merge into one that adjusts its sizes by screen width. You also fix an error caused by two forms sharing one global key, and see why short text widgets such as SansBold keep the code readable.
Code on GitHub: Portfolio app (complete)
- 143 Introduction to reusing code What reuse means, and why the portfolio repeated code so far 3 min
- 144 Reuse the web navigation tabs A TabsWebList widget, plus Ctrl+W to select whole widgets 4 min
- 145 Reuse the web navigation drawer A DrawersWeb widget that carries the URL launcher function 3 min
- 146 Reuse the mobile navigation drawer A DrawersMobile widget with the web drawer's link buttons 3 min
- 147 Merge the blog pages into one file A common folder, one Blog widget and an isWeb width check 3 min
- 148 Adapt the shared blog page by screen width Title, sizes and padding set by isWeb; old blog files deleted 5 min
- 149 Reuse the web contact form One ContactFormWeb widget for the landing and contact pages 4 min
- 150 Why use custom text widgets Sans and SansBold read better than restyling Text each time 1 min
- 151 Reuse the mobile contact form ContactFormMobile, shared controllers and a GlobalKey per form 4 min
- 152 Reuse the teal skill tags One tealContainer function for all skill tags, and one logger 4 min
20 Advanced State management
You see why big apps need state management, a way to keep shared data in step across every widget that shows it, and meet Dart mixins, which add one class's abilities to another through the with keyword. You build a counter with the Provider package, whose ChangeNotifier tells widgets when a value changes, then again with Riverpod, its successor, where autoDispose resets state no screen is using. Finally you run a function in an isolate, a separate thread with its own memory, so heavy work cannot freeze the app.
Code on GitHub: Provider project Riverpod project Multithreading example
- 153 Introduction to advanced state management Why apps need it, MVC and MVVM at a glance, and Dart mixins 8 min
- 154 Provider and the counter starter project A view and view model split for a simple counter app 2 min
- 155 A counter with Provider and ChangeNotifier ChangeNotifierProvider, Consumer and notifyListeners 5 min
- 156 Riverpod, the successor to Provider ProviderScope and an autoDispose ChangeNotifierProvider 4 min
- 157 A counter with Riverpod and ConsumerWidget WidgetRef, ref.watch and when autoDispose resets state 5 min
- 158 Multithreading with Dart isolates Run work on another thread with Isolate.spawn 9 min
21 Flutter Software Architectures
You learn what software architecture is, a blueprint for how an app's parts fit together, then build a counter app three ways, each after a theory lesson: MVC (Model View Controller), MVVM (Model View ViewModel) and BLoC (Business Logic Component), where taps become events and the screen redraws from the states that come back. Three lessons without code then cover clean architecture, which keeps business rules apart from the interface and database, and domain-driven design, which shapes code around the business.
Code on GitHub: Flutter architectures: MVC, MVVM, BLoC
- 159 Introduction to software architecture Why apps need a blueprint and three common misconceptions 10 min
- 160 MVC: Model View Controller What the model, view and controller do, with pros and cons 12 min
- 161 A counter app in MVC Separate model, controller and view files for a counter 13 min
- 162 MVVM: Model View ViewModel Roles, origins, data flow, benefits and pitfalls of MVVM 18 min
- 163 A counter app in MVVM Model, view model and view files linked by a callback 15 min
- 164 BLoC: Business Logic Component Events, states, streams and the flutter_bloc widgets 20 min
- 165 A counter app with BLoC Events, states, BlocProvider and BlocBuilder in flutter_bloc 23 min
- 166 Clean architecture and DDD: the theory Layers and use cases; domain-driven design's bounded contexts 22 min
- 167 Domain-driven design for a social network Entities, services and bounded contexts, benefits and costs 7 min
- 168 Keeping clean architecture and DDD on track Refining layers and contexts, and avoiding over-engineering 8 min
22 Budget App using Flutter Riverpod and MVVM architecture
After setting up Firebase for Android, iOS and the web, you build a budget app with Riverpod and the MVVM pattern, giving narrow and wide screens their own layouts. Users register or log in with email and password or Google Sign-In, and Firebase's error messages appear in a pop-up. On the dashboard they add expenses and income through validated pop-up forms that save to Cloud Firestore, see the lists and totals update live through streams, clear everything with a reset button and log out from a side drawer.
Code on GitHub: Budget app starting project Budget app complete project
- 169 Set up Firebase, Riverpod and the login screen Three platforms, sign-in state, and email and password fields 1 h
- 170 Creating a custom reusable widget An Open Sans text widget and the styled register button 4 min
- 171 Rows and user registration Why a Row re-centres the Column, then registering by email 4 min
- 172 Error pop-ups An AlertDialog that shows Firebase's error messages 7 min
- 173 Cleaning error messages with RegExp Strip the bracketed code from Firebase errors with replaceAll 4 min
- 174 Creating the log-in button An OR label, then signInWithEmailAndPassword and its errors 6 min
- 175 Registering and logging in to the app Test both buttons on Chrome after an emulator network bug 4 min
- 176 Creating the Google Sign-In button The sign_button package and kIsWeb to pick web or mobile 3 min
- 177 Google Sign-In functions for web and mobile A pop-up on the web and the google_sign_in package on phones 5 min
- 178 Connecting Google Sign-In to Firebase Auth Turn Google tokens into a credential for signInWithCredential 2 min
- 179 Google button wiring and the web login page Pick the web or mobile sign-in, then start the web layout 4 min
- 180 Adding image assets The login illustration and logo on the web login page 2 min
- 181 Email field for the web login A TextFormField with rounded borders and an email icon 5 min
- 182 Password field for the web login A show-or-hide toggle, then the start of the register button 3 min
- 183 Register and log-in buttons for the web Styled buttons with an OR label, wired to the view model 4 min
- 184 The Google Sign-In button on the web A large Google button, kIsWeb and a placeholder dashboard 3 min
- 185 Testing sign-in on the web and a phone Email and Google sign-in on Chrome, Google on a phone 4 min
- 186 A Firestore rule and the totals calculation A signed-in-only rule, then lists and the expense total loop 6 min
- 187 Budget left and the dashboard drawer Income total and a drawer header with a round logo 4 min
- 188 Log-out button in the drawer AppBar icon theme, then signOut from a styled button 6 min
- 189 Social media links An Instagram icon button with url_launcher and an SVG 2 min
- 190 Twitter link and the dashboard title A reusable Poppins text widget for the AppBar title 5 min
- 191 Reset button and TODO comments An AppBar action left empty and marked with a TODO comment 3 min
- 192 Building the totals box A ListView body and a black rounded container for totals 4 min
- 193 Totals labels and a vertical divider Poppins labels and a Divider turned with RotatedBox 4 min
- 194 Totals values and the add expense button Budget left and both totals, then a styled black button 6 min
- 195 The add expense pop-up A dialog with a Form, a GlobalKey and two text controllers 6 min
- 196 A reusable text form widget Label, validator, digits-only input and red error borders 7 min
- 197 Name and amount fields for expenses The text form widget in the pop-up, validated on Save 7 min
- 198 A reference to the users collection A CollectionReference so later code stays short 1 min
- 199 Saving expenses to Cloud Firestore A per-user expenses collection, error dialog and test entry 7 min
- 200 Creating the add income button Check the expense in the Firebase console, then the button 4 min
- 201 The add income pop-up A dialog with a form key and controllers for name and amount 4 min
- 202 Name and amount fields for income Validated fields, with digits-only amounts on both forms 3 min
- 203 Saving income to Cloud Firestore Validate, save to the incomes collection and close the pop-up 5 min
- 204 Expenses list box on mobile A heading and a bordered container to hold the expenses 3 min
- 205 Showing expenses with ListView.builder Name and amount rows, then the incomes box beside them 6 min
- 206 Incomes list and the expenses stream Finish the mobile layout, then listen with snapshots() 4 min
- 207 Reading Firestore documents into clean lists Empty the lists on each update to avoid duplicates 4 min
- 208 Starting the streams only once An isLoading flag to stay within Firestore's free reads 4 min
- 209 Resetting the budget, then the web dashboard Delete every expense and income, then copy logic to the web 6 min
- 210 Web dashboard drawer and AppBar Logo, log-out button, social links and the Dashboard title 8 min
- 211 Web dashboard layout and add expense button Reset action, a large illustration and the first button 5 min
- 212 Add expense and add income buttons on the web Icon buttons that open the same pop-ups as on mobile 6 min
- 213 Totals box for the web dashboard Budget left, total expense and total income at a larger size 7 min
- 214 Expenses list on the web dashboard A black card with a heading and a ListView of expenses 10 min
- 215 Incomes list and the finished budget app Test with a second account, reset and try other colours 8 min
23 Budget app: performance optimisation and code reuse
In one lesson, you return to the budget app and stop its endless rebuilding by moving the sign-in check to a Riverpod StreamProvider, which hands widgets the latest value from a stream. You then turn repeated code, from the login fields and buttons to the drawer, add buttons and totals box, into shared widgets, several as pause-and-try challenges. Finally you move the totals calculation into the view model and turn each Firestore document into a model object through a fromJson constructor.
Code on GitHub: Budget app complete project
- 216 Performance optimisation and code reuse StreamProvider for sign-in, shared widgets and a model class 58 min
24 Flutter Networking: Build Robust Apps with API Integration
You learn what an API (application programming interface) is, pictured as a restaurant menu, and how REST APIs, the most common kind, work: the GET, POST, PUT and DELETE methods, status codes such as 200 and 404, the JSON and XML data formats, and versioning. With JSONPlaceholder, a free fake back end for practice, you send a GET request with Dio, a package for web requests, and read the response, status code and headers, then walk through code that creates, replaces, partly updates (PATCH) and deletes posts.
Code on GitHub: REST with Dio: JSONPlaceholder app
- 217 Networking overview Beyond Firebase: APIs to back ends in PHP, Django or Java 23 min
- 218 What is an API? A restaurant-menu analogy, client-server apps and API uses 13 min
- 219 Types of API: REST, GraphQL and gRPC A recap of API basics that names REST, GraphQL, SOAP and gRPC 13 min
- 220 Introduction to REST APIs HTTP methods, status codes, JSON and XML, and versioning 8 min
- 221 A Dio GET request that prints comments JSONPlaceholder data, status code and headers in the console 21 min
- 222 POST, PUT, PATCH and DELETE with Dio A code walk-through: create, replace, update and delete posts 10 min
25 Continuous integration with GitHub Actions
In one lesson, you learn what CI/CD (continuous integration and continuous deployment) is for and set up its first half, continuous integration, with GitHub Actions, GitHub's automation service, on the finished launchpad app. You walk through a workflow file that runs on every push, building the Windows, Android, web and iOS versions on separate GitHub machines and saving the Windows, Android and web builds for download, then watch it run. You also see how a flutter test step would run your tests.
- 223 Automatic builds with GitHub Actions Build Windows, Android, web and iOS apps on every push 22 min
Instructors
Who teaches it.
Instructor, Flutter
Paulina Knop
Flutter developer and curriculum designer. Teaches the Flutter course.
Requirements
- A Windows, Mac or Linux computer able to run Flutter and an emulator or a real phone.
- Basic programming familiarity helps but is not required; Dart is taught from the start.
Who it is for
- Anyone who wants to create apps for Android and iOS, build websites and develop back-end systems with one language.
- Developers moving to Flutter from web or native mobile development.
- Beginners who want one path from first widget to a published app.
- Teams standardising on Flutter who need a shared, production-minded foundation.
What this course is
Welcome to the best and most industry-oriented hands-on Flutter development course. Flutter is Google’s open-source framework for building apps from one codebase, and here you start from scratch and go step by step until you work like an industry-standard Flutter developer. The curriculum was designed from over 2,000 job descriptions and perfected over a year, and it covers every fundamental of Flutter development in about 23 hours of lessons: Dart, the widget system, layouts, animations, responsive handling, Streams and Futures, state management with Riverpod, Firebase, REST APIs, navigation, design patterns and a GitHub Actions workflow that builds your app automatically.
By the end you will be able to build apps that meet industry standards, with a portfolio of nine real apps and more than 150 widgets used along the way, and go after Flutter developer jobs with confidence.
How it is taught
Project-first. You build real apps and learn each concept at the moment you need it, with the reasoning behind every decision, not just the clicks. The course has been followed by more than 30,000 students in 175 countries and is kept up to date as Flutter changes.
Who teaches it
Sagnik Bhattacharya, a technology consultant who has trained corporate teams and taught Flutter to over 30,000 students, together with Paulina Knop, instructor, curriculum designer and Flutter developer.
What you get
Everything a course should come with.
-
Lifetime access
Come back to any lesson whenever you need it, with future updates included.
-
Free preview lessons
Watch the opening lessons of every course before you decide.
-
Certificate of Completion
A PDF certificate with a verification link, emailed when you finish.
-
Projects you keep
Every section ends with something you built: a dashboard, an app screen, an automation.
-
Instructor support plan
One month of questions answered by the instructor, plus Ask AI in every lesson for immediate answers drawn from that lesson, labelled as AI. Activate it whenever you choose.
-
Team plans
Several seats at a per-seat discount, with a team area to follow progress.
Questions
Frequently asked.
Is this course for me?
Yes, if you want to create apps for Android and iOS, build websites and develop back-end systems. It starts from scratch and goes step by step.
Can I build a website with this course?
Yes. The portfolio project is built for the web as well as for phones, and you deploy it to Firebase Hosting.
Can I build Android and iOS apps at once with Dart only?
Yes. With Dart and Flutter you build Android and iOS apps, and websites, from one codebase in one programming language.
Is this a full-stack course?
Yes. It covers the front end and, with Firebase, the back end of mobile and web apps, including authentication, a cloud database, security rules and hosting.
Do I need to know Dart first?
No. Dart is taught in the course before the Flutter sections rely on it.
How long do I have access?
Lifetime access, including future updates to the course.
Do I get a certificate?
Yes. A Certificate of Completion is issued as a PDF and emailed to you, with a verification link, and you can show it on your LinkedIn profile.
What does the support option include?
One month of questions answered by the instructor through the inbox under each lesson, activated whenever you choose.
What if it is not for me?
There is a 14-day money-back guarantee. Details are in the refund policy.
Ready?
Start Flutter today.
USD 10 for lifetime access, or USD 49 with a month of instructor support. 14-day money-back guarantee.
Questions first? Contact us or chat on WhatsApp .