When you execute flutter create my_app, Flutter generates a directory tree containing native host files, dependency manifests, test suites, and Dart source code. Understanding the Flutter Project Structure is essential for maintaining clean codebases, configuring platform permissions, managing assets, and scaling cross-platform applications.

Overview of the Generated Directory Tree

A fresh Flutter project presents a modular file system designed to separate platform-specific logic from your core application logic. Below is the tree view of a standard Flutter project layout:

Code
my_app/
├── .dart_tool/
├── android/
├── build/
├── ios/
├── lib/
│   └── main.dart
├── linux/
├── macos/
├── test/
│   └── widget_test.dart
├── web/
├── windows/
├── .gitignore
├── analysis_options.yaml
├── pubspec.lock
├── pubspec.yaml
└── README.md

1. Root Configuration and Meta Files

At the root of your project structure lie project configuration files that control dependencies, static analysis, and platform constraints.

pubspec.yaml

The pubspec.yaml file is the central setup file for dependencies and project metadata. It defines third-party packages, app versioning, Dart SDK boundaries, and declared asset paths (such as images or fonts).

Code
name: my_app
description: "A new Flutter project."
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/logo.png

pubspec.lock

Automatically generated when dependencies are retrieved via flutter pub get. It locks the exact versions of all direct and transitive packages to ensure reproducible builds across different development machines and CI/CD environments. Do not edit this file directly.

analysis_options.yaml

Configures rules for the Dart static analyzer and linter. It enforces code quality, style guidelines, and best practices across your project.

.dart_tool/ and .gitignore

The .dart_tool/ directory is used by the Dart SDK to track package resolution and build artifacts. The .gitignore file specifies local build files and generated paths that should not be tracked by Git.

2. Core Application Logic: The lib/ Directory

The lib/ folder contains cross-platform Dart code. This is where primary application feature code resides. By default, Flutter provides an entry point at lib/main.dart.

The Entry Point: main.dart

The execution of every Flutter application starts inside lib/main.dart within the top-level main() function, which invokes

Code
runApp()
.
Dart / Flutter
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: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Screen'),
      ),
      body: const Center(
        child: Text('Flutter Project Structure Guide'),
      ),
    );
  }
}
Pro Tip: Avoid putting all widget and business logic inside main.dart. As applications grow, separate your lib/ folder using structured architectural patterns such as Feature-First or Layer-First organization.

Recommended Architecture inside lib/

For scalable codebases, a feature-based folder organization helps maintain modularity and domain separation:

Code
lib/
├── main.dart
├── core/
│   ├── constants/
│   ├── network/
│   └── theme/
└── features/
    ├── authentication/
    │   ├── data/
    │   ├── logic/
    │   └── presentation/
    └── dashboard/
        ├── data/
        ├── logic/
        └── presentation/

3. Native Target Directories: android/, ios/, web/, and Desktop

Flutter compiles Dart code into native instructions. To host that native application, platform-specific wrapper folders are generated.

android/ Folder

Contains a native Android Gradle project. Android-specific settings like minSdkVersion, package name, and dependencies are managed in android/app/build.gradle. Custom Kotlin or Java code and platform permissions reside inside android/app/src/main/.

ios/ Folder

Contains an Xcode workspace for iOS target devices. Configuration files like Info.plist (used for setting permissions like Camera or Location access) and CocoaPods dependencies (Podfile) are managed within this folder.

web/ Folder

Contains the web application entry shell, including index.html, single-page application entry points, PWA manifest configurations, and favicon assets.

windows/, macos/, linux/ Folders

Contain native C++ or Swift runner applications that launch your Flutter application code on desktop operating systems.

4. Automated Tests: test/

The test/ folder is designated for automated testing. By default, Flutter generates a basic widget test inside test/widget_test.dart. Maintain unit, widget, and integration tests inside this folder mirroring your lib/ structure.

Dart / Flutter
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/main.dart';

void main() {
  testWidgets('Verify Home Screen render test', (WidgetTester tester) async {
    await tester.pumpWidget(const MyApp());
    expect(find.text('Flutter Project Structure Guide'), findsOneWidget);
  });
}

5. Build Output Directory: build/

The build/ directory stores dynamic output generated during platform builds (e.g., APKs, IPAs, dynamic web bundles, and intermediate object files). This directory is managed by the Flutter engine and should remain in .gitignore.

Summary Checklist

  • lib/: Main location for Dart source code, application state, and UI.
  • pubspec.yaml: Project metadata, external package declarations, and local assets.
  • android/ & ios/: Native host project files and hardware permission declarations.
  • test/: Unit, widget, and mock testing suites.
  • build/ & .dart_tool/: Auto-generated local compilation artifacts.

Frequently Asked Questions

Why are there native folders like android/ and ios/ if Flutter is cross-platform?

Flutter apps run embedded inside a native host application shell. The android/ and ios/ folders hold the native project files, app permissions (e.g., AndroidManifest.xml, Info.plist), target SDK configurations, and native code integration hooks required by mobile platforms.

Can I delete platform folders like web/ or windows/ if I am building only for mobile?

Yes. If you do not plan to release your project on desktop or web platforms, you can safely remove those platform directories. If you ever need them later, running 'flutter create .' in the project root recreates missing platform directories.

Where should I store assets like images, fonts, and local data files?

Create a top-level directory named 'assets/' in your project root (e.g., assets/images/, assets/fonts/). After placing your files there, explicitly declare them in your pubspec.yaml file under the 'flutter: assets:' block.

What is the difference between pubspec.yaml and pubspec.lock?

pubspec.yaml is a developer-managed file where you define your high-level packages and version requirements. pubspec.lock is auto-generated by Flutter to record the exact resolved versions of every package and dependency tree level to ensure consistent builds.