Setup and your first app

Install the Flutter SDK, understand what a project contains, and read the counter app that every new project starts from.

Install and check the toolchain

# macOS / Linux: download the SDK, then put it on PATH
export PATH="$PATH:$HOME/flutter/bin"

flutter doctor            # reports missing SDKs, licences, devices
flutter doctor --android-licenses
flutter devices           # emulators, simulators and physical phones

flutter create --org com.example --platforms=android,ios notes
cd notes
flutter run
  • Flutter ships the Dart SDK and the engine; you still need the Android SDK or Xcode to build for those platforms.
  • flutter doctor is the first thing to run whenever a build fails for a reason that is not in your code.
  • Hot reload applies code changes in under a second without losing state. Press r in the run console.

What the project contains

PathPurpose
lib/main.dartDart entry point; the app starts at main()
pubspec.yamlPackage name, dependencies, assets, fonts
android/ and ios/Native host projects; edit them for permissions and platform config
test/Widget and unit tests run by flutter test
.dart_tool/ and build/Generated output; never edit and never commit
name: notes
description: A small notes app.
publish_to: none
version: 1.0.0+1

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.3.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

Reading main.dart

import 'package:flutter/material.dart';

void main() => runApp(const NotesApp());

class NotesApp extends StatelessWidget {
  const NotesApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Notes',
      theme: ThemeData(colorSchemeSeed: Colors.indigo),
      home: const CounterPage(),
    );
  }
}

class CounterPage extends StatefulWidget {
  const CounterPage({super.key});

  @override
  State<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Notes')),
      body: Center(child: Text('Pressed ' + count.toString() + ' times')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => count++),
        child: const Icon(Icons.add),
      ),
    );
  }
}
💡
Everything on screen is a widget, including padding and center. When a layout looks wrong, add temporary Container(color: ...) boxes to see which widget actually occupies which rectangle.

FAQ

Do I need to learn Dart first?
You need the basics: types, null safety, classes, async and await, and simple generics. Dart is small, and Flutter code reads naturally once those click.
Why does hot reload sometimes not update the UI?
Hot reload keeps state, so edits to initState, top-level variables or const-constructed subtrees may need a hot restart (R) or a full rebuild.

Widgets and layout State, navigation and release builds

Last refreshed 2026-09-18.