All Guides
    Flutter Basics
    Flutter Basics
    Getting Started
    CLI

    Your First Flutter App

    Published April 2026

    Introduction

    Embarking on the journey of cross-platform mobile development can feel daunting with complex configurations and boilerplate setups. Fortunately, Flutter provides one of the most streamlined onboarding experiences in the modern software engineering space. By leveraging Google's Software Development Kit (SDK), developers can create applications that run flawlessly across mobile, web, and desktop environments from a single codebase.

    In this guide, you will learn how to initialize your very first Flutter project from scratch using the Command Line Interface (CLI). We will demystify the automatically generated folders, dissect the entry point of a Flutter application, and build a compiler-valid, interactive welcome screen. This hands-on process helps you understand how Flutter translates code configurations into high-performance visual interfaces.

    By the end of this tutorial, you will have a fully functioning application running on your emulator or physical device. You will also understand the exact flow of data from the Dart compiler down to the rendering window, establishing a solid foundation for the remainder of your learning path.


    Prerequisites

    Before building your application, ensure that you have configured your environment:

    • Installed the Flutter SDK and added the tools to your terminal PATH.
    • Set up a code editor (we highly recommend VS Code with Flutter and Dart extensions installed).
    • Configured an emulator (Android Emulator or iOS Simulator) or enabled developer mode on a physical device connected to your machine.
    • Verify your installation by running flutter doctor in your terminal. All primary checkmarks should show as green.

    Core Explanation: The Flutter CLI & Directory Structure

    To start building, we must generate the project template using the Flutter CLI. The terminal commands are straightforward and prepare a boilerplate layout with support for Android, iOS, Web, and Desktop environments.

    Project Initialization

    Open your terminal, navigate to your desired workspace, and execute the following command:

    flutter create my_first_app
    

    This creates a new folder named my_first_app containing the standard structure. Open this directory in your editor:

    cd my_first_app
    

    Understanding the Directory Tree

    The generated folder contains several files. Here are the core files you must understand:

    • lib/: This is the heart of your application. Almost all of your Dart code, widgets, and logic will be written in this directory. By default, it contains the main entry point: lib/main.dart.
    • pubspec.yaml: The project configuration file. This is where you declare app metadata, manage dependency packages (like HTTP tools or database interfaces), and define local assets (images, custom fonts).
    • android/, ios/, web/, linux/, macos/, windows/: These folders contain the platform-specific wrapper projects. When you compile your app, the Flutter build tool uses these templates to embed the Dart compiler engine and generate target bundles.

    The Entry Point

    Every Flutter app starts at the main() function, located in lib/main.dart. This function executes first, calling runApp(). The runApp() method binds the root widget to the device screen, launching the framework engine.


    Practical Example: Building a Welcome App

    Let's write a complete, compiler-ready welcome application. Replace the entire content of your lib/main.dart file with the following clean code block:

    import 'package:flutter/material.dart';
    
    void main() {
      // The entry point of the app, running our root widget.
      runApp(const MyApp());
    }
    
    /// The root widget of the application.
    /// It configures global theme styles and launches the Home screen.
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'My First App',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const WelcomePage(),
        );
      }
    }
    
    /// The home screen widget representing our interactive page.
    class WelcomePage extends StatefulWidget {
      const WelcomePage({super.key});
    
      @override
      State<WelcomePage> createState() => _WelcomePageState();
    }
    
    class _WelcomePageState extends State<WelcomePage> {
      // Interactive state parameter tracking the greeting status
      bool _isLiked = false;
    
      void _toggleLike() {
        setState(() {
          _isLiked = !_isLiked;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Welcome to Flutter'),
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            centerTitle: true,
          ),
          body: Center(
            child: Padding(
              padding: const EdgeInsets.all(24.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text(
                    'Hello World!',
                    style: TextStyle(
                      fontSize: 32,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16.0),
                  Text(
                    'You have successfully built and run your first Flutter application. This interactive greeting responds to state modifications.',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.grey[700],
                    ),
                  ),
                  const SizedBox(height: 24.0),
                  // Conditional text display based on state
                  Text(
                    _isLiked ? 'Thank you for liking!' : 'Do you like this guide?',
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w600,
                      color: _isLiked ? Colors.deepPurple : Colors.grey[800],
                    ),
                  ),
                ],
              ),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _toggleLike,
            tooltip: 'Toggle Like',
            child: Icon(
              _isLiked ? Icons.favorite : Icons.favorite_border,
              color: Colors.red,
            ),
          ),
        );
      }
    }
    

    Code Explanation:

    1. package:flutter/material.dart: Imports Flutter's standard Material Design widgets.
    2. MaterialApp: The root configuration component that sets up themes, titles, and routing.
    3. Scaffold: Implements the basic Material visual layout structure (app bar, body padding, and floating action button placeholders).
    4. StatefulWidget & setState: Allows us to keep track of variables (like _isLiked) and call setState to tell Flutter to redraw the screen when they change.

    Visual Breakdown

    Let's examine how the widget trees translate during runtime initialization:

    MyApp (Root Configurations)
      └── MaterialApp (Material contexts, fonts, styles)
            └── WelcomePage (Stateful Component Container)
                  └── Scaffold (Basic layout scaffolding structure)
                        ├── AppBar (Header bar with titles)
                        ├── Center (Centering viewport container)
                        │     └── Padding (Inner padding bounds)
                        │           └── Column (Vertical linear layout)
                        │                 ├── Text ("Hello World!")
                        │                 ├── SizedBox (Spacing spacer)
                        │                 ├── Text (Body description)
                        │                 ├── SizedBox (Spacing spacer)
                        │                 └── Text (Conditional status string)
                        └── FloatingActionButton (Interactive trigger button)
    
    • Execution Flow: When the FloatingActionButton is tapped, _toggleLike is called. The internal setState updates the boolean value of _isLiked, triggering a repaint of WelcomePage and updating the text on the screen.

    Common Mistakes

    1. SDK Version Conflict

    Running commands and getting "The current Dart SDK version is..." errors is very common.

    • The Fix: Ensure your pubspec.yaml target SDK version matches your installed version. Running flutter upgrade updates your local toolsets.

    2. Missing MaterialApp Root

    Trying to run widgets without wrapping them in a MaterialApp or CupertinoApp root container will cause text rendering issues (such as double yellow underline decorations).

    • The Fix: Always declare a MaterialApp or CupertinoApp at the very top of your widget structure to provide text direction and theme contexts.

    3. Modifying Platform Directories Directly

    New developers often attempt to build native screens in /android or /ios files directly instead of composing layouts inside the /lib folder.

    • The Fix: Keep all UI layout setups in /lib and rely on Flutter's compiler to generate native views. Only open platform directories for native configuration details (like app icons or key sign certificates).

    Best Practices

    • Run flutter doctor Proactively: Whenever you hit compilation crashes, run flutter doctor to detect configuration issues in your toolsets.
    • Leverage Auto-Formatting: Use Dart's built-in formatting tools (dart format . or VS Code shortcut) to ensure your code formatting remains clean and readable.
    • Keep Platform Folders Intact: Do not delete platform folders unless you explicitly plan to re-generate them using flutter create ..

    Related Concepts

    Continue your Flutter learning journey by exploring these related topics:


    Summary

    • Use flutter create to initialize a new project layout from the terminal.
    • Your Dart code lives in /lib, and dependency configurations are managed in pubspec.yaml.
    • The main() function is the application entry point, executing runApp() to start the framework engine.
    • Flutter updates the screen dynamically by rebuilding layout configurations whenever state modifications trigger setState.

    Next Steps

    1. Next Guide: Understanding Widgets in Flutter
    2. Related Guide: Stateless vs. Stateful Widgets
    3. Related Guide: Row vs. Column Layout Guide

    Ready to take the next step?

    Start our free Flutter course and build real apps today.

    Start Learning Now