1. Dart in Five Minutes
Dart is the language Flutter is built on — a curly-brace, statically-typed language that will feel immediately familiar if you've written TypeScript, Java, C#, or Kotlin. A few things matter from day one:
// var infers the type; the type is fixed once assigned
var name = 'Ada'; // inferred as String
int age = 36;
final city = 'London'; // final: assigned once, at runtime
const pi = 3.14159; // const: a compile-time constant
// Dart is sound null-safe: a type is non-nullable unless you add ?
String greeting = 'Hello'; // can never be null
String? nickname; // can be null -- must be declared explicitly
// The ?? and ?. operators handle nullable values safely
print(nickname ?? 'no nickname set'); // prints the fallback if null
print(nickname?.length); // null instead of crashing
Every variable in Dart is non-nullable by default — this is the
single most important difference from JavaScript. If a function expects a
String, passing null is a compile-time error, not a
runtime surprise. Anywhere a value is genuinely optional, mark the type with
? explicitly.
// A function with a typed parameter and typed return value
int add(int a, int b) {
return a + b;
}
// Named parameters (common in Flutter's own APIs) use {} and can be required
String describe({required String name, int age = 0}) {
return '$name is $age years old';
}
describe(name: 'Ada', age: 36);
// A simple class with a constructor
class Person {
final String name;
final int age;
Person({required this.name, required this.age});
String greet() => 'Hi, I\'m $name';
}
final ada = Person(name: 'Ada', age: 36);
print(ada.greet());
Almost every widget constructor you'll write from Week 2 onward uses named parameters (Container(color: ..., width: ...)) rather than positional ones — get comfortable with the {required this.x} pattern now, since it's the shape of nearly every widget you'll build.
2. Installing Flutter
Download the Flutter SDK for your OS from flutter.dev, add it to your PATH, then verify the whole toolchain in one command:
flutter doctor
flutter doctor checks the Flutter SDK itself, plus every platform
toolchain it can build for — Android Studio/SDK for Android, Xcode for iOS (Mac
only), and your connected devices/emulators — and prints a checklist of what's
missing. Don't move on until at least one platform shows a green checkmark.
iOS builds require a Mac with Xcode — if you're on Windows or Linux, install Android Studio and target the Android emulator or a physical Android phone for this entire course. Everything you learn transfers directly once you do have access to a Mac for iOS builds.
Install the Flutter and Dart extensions for VS Code (or the Flutter plugin for Android Studio) — they add syntax highlighting, a device picker, and one-click debugging, and are what this course assumes you're using throughout.
3. Creating a Project
Scaffold a new project and step into it:
flutter create my_app
cd my_app
flutter run
my_app/
├── lib/
│ └── main.dart ← the entry point -- your app starts here
├── pubspec.yaml ← dependencies, assets, app metadata
├── android/ ← native Android project (edited rarely)
├── ios/ ← native iOS project (edited rarely)
├── test/ ← unit & widget tests
└── web/ ← native web project, if enabled
pubspec.yaml is Flutter's equivalent of package.json —
it lists your dependencies (fetched from pub.dev, Dart's package
registry) and declares any asset files (images, fonts) your app bundles:
name: my_app
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: '>=3.3.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.6
flutter:
uses-material-design: true
Adding a package is one command — flutter pub add http adds
http as a dependency and writes it into pubspec.yaml
automatically, the same way npm install would.
4. Running on a Device
List whatever's available, then run against a specific target:
# See every connected device/emulator/simulator Flutter can see
flutter devices
# Run on a specific device by ID
flutter run -d emulator-5554
# Just run -- Flutter picks a device automatically if only one is connected
flutter run
Once the app is running, two commands drive the entire development loop, both triggered from the terminal Flutter is running in (or a single keypress/button in your editor):
- Hot reload (press
r) — injects updated source code into the running app in under a second, preserving current app state (like which screen you're on). This is what you'll use for the vast majority of edits. - Hot restart (press
R) — rebuilds and restarts the app from scratch, resetting all state. Needed when a change hot reload can't handle, like editingmain()or adding a new class field.
This sub-second feedback loop is one of Flutter's defining features — you'll edit a widget's padding or color and see it change on a real device almost instantly, without losing your place in the app. Get used to leaving flutter run running in a terminal the entire time you work.
5. Your First Widget
lib/main.dart is the entry point. The single governing idea in
Flutter, which every week of this course builds on, is this: everything
is a widget — not just buttons and text, but padding, alignment, and
layout are all widgets too, composed into a tree.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('My App')),
body: const Center(
child: Text(
'Hello, Flutter!',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
),
),
);
}
}
Reading this top to bottom, in the order Flutter actually needs it:
runApp()takes a widget and makes it the root of the entire app — everything else nests inside itMaterialAppsets up app-wide concerns: theming, navigation, and Material Design defaults (aCupertinoAppvariant exists for iOS-styled apps)Scaffoldprovides the basic visual structure of a screen — an app bar, a body, and slots for things like floating action buttons and navigation drawersCenterandTextare themselves widgets, nested insideScaffold'sbody— this nesting is the layout, there's no separate stylesheet describing it
Every widget class overrides a build(BuildContext context) method
that returns the widget(s) it renders — Flutter calls build again
whenever a widget needs to redraw, which is the mechanism behind hot reload and,
starting next week, interactivity.
6. Hands-on Exercise
Scaffold a project and get it running on your own device
The whole point of this week is proving the full loop works end to end before any real code gets written.
Requirements:
- Run
flutter doctorand resolve every issue for at least one platform (Android is enough on Windows/Linux). - Run
flutter create my_app, thenflutter runand confirm the default counter app loads on an emulator, simulator, or physical device. - Replace
main.dartwith theHomeScreenexample above, changing the title, the greeting text, and the font size. - With
flutter runstill active, edit the text again and pressrin the terminal to hot reload — confirm the change appears without losing app state. - Write a small
Person-style Dart class of your own (e.g.Bookwithtitle,author, a named constructor, and a method that returns a formatted string) and print an instance of it to the debug console withdebugPrint().
If flutter run can't find a device, run flutter emulators --launch <emulator_id> to start one, or plug in a physical phone with USB debugging (Android) or via Xcode (iOS) enabled.
7. Knowledge Check
Four quick questions. Expand each to check your answer.
Q1
What does adding ? to a type, like String? nickname, actually change?
What does adding ? to a type, like String? nickname, actually change?
Dart types are non-nullable by default, so String nickname can never legally hold null — the compiler rejects it. Adding ? explicitly opts the type into being nullable, which then requires handling the null case (with ??, ?., or an explicit check) wherever the value is used.
Q2
What's the practical difference between hot reload and hot restart?
What's the practical difference between hot reload and hot restart?
Hot reload injects your changed source code into the already-running app in under a second, keeping the app's current state (like which screen is open). Hot restart rebuilds and relaunches the entire app from scratch, resetting all state — necessary for changes reload can't apply, like edits to main() or new fields on an existing class.
Q3
What does the phrase "everything is a widget" actually mean in Flutter?
What does the phrase "everything is a widget" actually mean in Flutter?
Not just visible things like buttons and text are widgets — layout, padding, alignment and centering are widgets too (Center, Padding, Row). A screen is a tree of nested widgets, and the nesting itself is the layout; there's no separate stylesheet or layout language describing it the way CSS does on the web.
Q4
What does a widget's build(BuildContext context) method do, and when does Flutter call it?
What does a widget's build(BuildContext context) method do, and when does Flutter call it?
It returns the widget (or tree of widgets) that particular widget renders as. Flutter calls it once when the widget first appears, and again any time that widget needs to redraw — which is the same mechanism hot reload relies on, and starting next week, the mechanism setState uses to make widgets interactive.