Skip to content
FlutterLearn

Beginner · Lesson 1 · 9 min read

What Flutter Is and How to Set It Up

Understand what Flutter actually does under the hood, then install the SDK and run your first app on a simulator or real device.

Updated July 14, 2026

What you will learn

  • Explain how Flutter renders UI and why that matters
  • Install the Flutter SDK and verify it with flutter doctor
  • Create and run a project on a device or emulator
  • Understand what every file in a new project is for

Flutter is a UI toolkit from Google for building applications for mobile, web, desktop and embedded devices from a single Dart codebase. The part that surprises most newcomers is how it draws the screen: Flutter does not wrap the platform's native buttons and text fields. It ships its own rendering engine and paints every pixel itself.

How Flutter renders your UI

Your Dart code describes a tree of widgets. Flutter's framework turns that tree into a layout, and the engine (written in C++, using the Impeller renderer on modern releases) rasterises it onto a canvas provided by the operating system. The OS gives Flutter a window; everything inside that window is Flutter's.

  • Consistency — a Switch looks and behaves identically on Android 10 and iOS 18, because Flutter drew it, not the OS.
  • Speed of iteration — because the framework owns rendering, it can rebuild the UI from source in under a second (hot reload).
  • Trade-off — you do not automatically inherit new OS widget styles, and accessibility has to be bridged explicitly (Flutter does this for you via the semantics tree).

In release builds your Dart is compiled ahead-of-time to native ARM or x64 machine code. There is no JavaScript bridge and no interpreter in the hot path, which is why well-written Flutter apps feel native.

Installing the SDK

Download the SDK for your operating system from the official Flutter site, unzip it somewhere permanent (not your Downloads folder), and add its bin directory to your PATH.

Terminal (macOS/Linux)
# Add to ~/.zshrc or ~/.bashrc, then restart your shell
export PATH="$HOME/development/flutter/bin:$PATH"

# Verify the install and see what is still missing
flutter doctor -v

flutter doctor is the single most useful command you will run. It checks each toolchain and tells you exactly what is missing — an Android licence you have not accepted, a missing Xcode command-line tool, an absent device.

Terminal
# Accept Android SDK licences (Android development)
flutter doctor --android-licenses

# Install iOS tooling (macOS only)
sudo xcode-select --install
sudo xcodebuild -runFirstLaunch

Creating and running your first project

Terminal
flutter create my_first_app
cd my_first_app

# See which devices Flutter can see right now
flutter devices

# Run on the default device
flutter run

The project name must be a valid Dart package name: lowercase, words separated by underscores. my_first_app works; MyFirstApp does not.

Once the app is running, change a string in lib/main.dart and save. Press r in the terminal for hot reload — state is preserved and the change appears almost instantly. Press R for hot restart, which throws away state and rebuilds the app from scratch. Use hot restart whenever you change global variables, initState, or anything static.

What is in a new project

PathWhat it is for
lib/main.dartYour app's entry point. Nearly all your code lives under lib/.
pubspec.yamlPackage manifest: dependencies, assets, fonts, app version.
pubspec.lockResolved dependency versions. Commit this for apps.
android/, ios/Native host projects. You edit these for permissions, icons and signing.
test/Dart tests, run with flutter test.
analysis_options.yamlLint rules. Tighten these early — it costs nothing and catches real bugs.

The smallest possible Flutter app

Delete everything in lib/main.dart and paste this. It is a complete, runnable app.

lib/main.dart
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 First App',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      ),
      home: const HomeScreen(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Hello Flutter')),
      body: const Center(
        child: Text('Your first screen.'),
      ),
    );
  }
}

runApp takes a widget and makes it the root of the tree. MaterialApp provides routing, theming and localisation. Scaffold gives you the standard visual skeleton — app bar, body, floating action button, drawer. ColorScheme.fromSeed generates a full Material 3 palette from one colour.

Key takeaways

  • Flutter paints its own pixels with its own engine rather than wrapping native widgets.
  • flutter doctor -v diagnoses your toolchain; fix only the platforms you target.
  • Hot reload (r) keeps state, hot restart (R) resets it — reach for restart when changing initialisation code.
  • runApp mounts a root widget; MaterialApp + Scaffold supply app-level plumbing and visual structure.

Practice

Make it yours

Change the seed colour, the app bar title and the centred text. Then add a second line of text below the first using a Column. Run on both a simulator and a physical device and note the differences you see.

Show hints
  • Column takes a children list rather than a single child.
  • Wrap the Column in Center to keep it in the middle of the screen.