Your First Flutter App
From Empty Screen to Running App
Open interactive version (quiz + challenge)Real-world analogy
Building your first Flutter app is like building your first LEGO house. You start with a base plate (MaterialApp), add walls (Scaffold), put a sign on top (AppBar), and fill the room with furniture (widgets in the body). Each piece snaps into place, and when you are done, you have a real house -- or in this case, a real app!
What is it?
Your first Flutter app starts with main(), which calls runApp() to launch the widget tree. MaterialApp wraps the entire app with Material Design. Scaffold provides page structure (AppBar + body). StatelessWidget is the simplest widget type -- it builds UI that does not change.
Real-world relevance
Every Flutter app in the world, from small personal projects to apps used by millions, starts with this exact structure: main() -> runApp() -> MaterialApp -> Scaffold. Understanding this foundation is essential for everything that follows.
Key points
- main() - Where It All Begins — Every Dart program starts at the main() function. It is the entry point -- the first thing that runs. In Flutter, main() calls runApp() to launch your app. Without main(), your app has no starting point and cannot run.
- runApp() - Launch the App — runApp() takes a widget and makes it the root of your app. It fills the entire screen with that widget. You typically pass a MaterialApp widget to runApp(), which sets up Material Design styling for your whole app.
- MaterialApp - The App Shell — MaterialApp is the outermost widget that wraps your entire app. It provides Material Design theming, navigation, and other app-wide settings. Think of it as the shell of your app -- everything else lives inside it.
- Scaffold - Page Structure — Scaffold provides the basic visual structure for a page: an AppBar at the top, a body in the middle, and optionally a floating action button, bottom navigation bar, and drawer. Most screens in your app will use a Scaffold.
- StatelessWidget - Your First Widget — A StatelessWidget is a widget that never changes. Once built, it stays the same. It is the simplest type of widget. You create one by extending StatelessWidget and overriding the build() method to return your UI.
- Hot Reload in Action — While your app is running, change any text or color in your code, then save the file (Ctrl+S). Flutter's Hot Reload updates the app in under a second without losing the current state. It is the fastest way to develop apps.
- The Widget Tree — Flutter apps are a tree of widgets. MaterialApp contains Scaffold, Scaffold contains AppBar and body, body contains Center, Center contains Text. Each widget is a node in the tree, and the tree describes your entire UI.
- const Keyword for Widgets — Adding 'const' before a widget tells Flutter it will never change. This helps Flutter skip unnecessary rebuilds, making your app faster. Use const whenever a widget has no dynamic data.
- import Statement — The import statement brings in code from other files or packages. 'import package:flutter/material.dart' gives you access to all Material Design widgets. Without this import, Flutter widgets are not available in your file.
Code example
import 'package:flutter/material.dart';
// Every Flutter app starts here
void main() {
runApp(const MyApp());
}
// The root widget of our app
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My First App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorSchemeSeed: Colors.blue,
useMaterial3: true,
),
home: const HomePage(),
);
}
}
// Our first screen
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My First App'),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.flutter_dash, size: 80),
SizedBox(height: 20),
Text(
'Hello, Flutter!',
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Text('Welcome to your first app!'),
],
),
),
);
}
}Line-by-line walkthrough
- 1. Importing Flutter's material design library so we can use its widgets
- 2.
- 3. A comment explaining this is the starting point
- 4. main() function -- Dart runs this first when the app launches
- 5. runApp() takes our MyApp widget and displays it on screen
- 6.
- 7. A comment explaining this is the root widget
- 8. MyApp class extends StatelessWidget because it does not change
- 9. The const constructor that every StatelessWidget needs
- 10.
- 11. The @override annotation -- we are providing our own build method
- 12. build() is called by Flutter to get the widget tree for this widget
- 13. Returning a MaterialApp as the root widget
- 14. Setting the app title that appears in the task switcher
- 15. Hiding the red 'DEBUG' banner in the top-right corner
- 16. Setting up the visual theme for the entire app
- 17. Using a blue color seed for Material 3 color scheme
- 18. Enabling Material Design 3 (latest design system)
- 19. Closing the ThemeData
- 20. Setting HomePage as the first screen to display
- 21. Closing MaterialApp and build method
- 22.
- 23.
- 24. A comment for our home screen widget
- 25. HomePage is also a StatelessWidget with no dynamic state
- 26. Const constructor
- 27.
- 28. Override annotation for the build method
- 29. build() returns what this screen looks like
- 30. Returning a Scaffold for standard page structure
- 31. Creating an AppBar at the top of the screen
- 32. Setting the title text to 'My First App'
- 33. Using the theme's primary container color for the AppBar background
- 34. Closing AppBar
- 35. The body is the main content area -- Center places content in the middle
- 36. Using a Column to stack widgets vertically
- 37. mainAxisAlignment centers the column content vertically
- 38. Opening the children list
- 39. An Icon widget showing the Flutter Dash mascot at size 80
- 40. SizedBox adds 20 pixels of vertical spacing
- 41. A large bold Text widget saying 'Hello, Flutter!'
- 42. TextStyle sets font size to 28 and bold weight
- 43. Closing the Text style
- 44. SizedBox adds 10 more pixels of spacing
- 45. A smaller Text widget with a welcome message
- 46. Closing children, Column, Center, body, Scaffold, and build
Spot the bug
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Text('Hello')
)
)
}
}Need a hint?
Look at the punctuation at the end of the return statement and check if the constructor is correct...
Show answer
Two issues: (1) Missing const constructor -- add 'const MyApp({super.key});' before @override. (2) Missing semicolons after the closing parentheses -- the return statement needs a semicolon: return MaterialApp(...);
Explain like I'm 5
Building a Flutter app is like building a house with LEGO. The main() function is you deciding to start building. runApp() is placing the first block down. MaterialApp is the foundation plate. Scaffold is the walls and roof. And all the little widgets inside (text, buttons, images) are the furniture and decorations. Save your work and Flutter magically shows you the house instantly!
Fun fact
The Flutter team at Google dogfoods their own framework -- the Google Ads app, used by millions of advertisers, is built entirely with Flutter! The default Flutter counter app you see when running 'flutter create' has been seen by over 10 million developers.
Hands-on challenge
Run 'flutter create my_app' in your terminal. Open lib/main.dart in VS Code. Change the title text and the counter description, then save to see Hot Reload in action. Try changing colors too!
More resources
- Write Your First Flutter App (Flutter Official)
- Flutter Widget Catalog (Flutter Official)
- Introduction to Widgets (Flutter Official)