Dart Tutorial

Flutter Lesson 4 of 83 2 min read

Flutter Project Structure Explained

Understand the folders and files in a Flutter project: lib, pubspec.yaml, android, ios, web and test, and how to organise your own code.

On this page

flutter create makes many files. You will work in only a few of them.

The folders #

my_first_app/
  lib/                    # your Dart code
    main.dart             # the app starts here
  test/                   # automated tests
  android/                # the native Android project
  ios/                    # the native iOS project
  web/                    # files for the web build
  windows/ macos/ linux/  # desktop projects
  build/                  # generated output
  .dart_tool/             # tool cache
  pubspec.yaml            # name, packages, assets, fonts
  pubspec.lock            # exact package versions
  analysis_options.yaml   # lint rules
PathHow often you touch it
lib/All the time. This is the app
pubspec.yamlWhen you add a package, an image or a font
test/When you write tests
android/, ios/Sometimes: app name, icon, permissions, signing
web/, desktop foldersRarely
build/, .dart_tool/Never. They are regenerated

pubspec.yaml #

name: my_first_app
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ^3.5.0

dependencies:
  flutter:
    sdk: flutter
  http: ^1.2.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/
  • version: 1.0.0+1 is the version users see, then a plus, then the build number that app stores require to go up with each upload.
  • Images and other files must be listed under assets before the app can load them.
  • YAML depends on indentation. Use two spaces, never tabs.

Organising lib as the app grows #

Do not keep everything in main.dart. Grouping by feature scales well:

lib/
  main.dart
  app.dart                  # MaterialApp, theme, routes
  features/
    auth/
      login_page.dart
      auth_service.dart
    products/
      product.dart
      product_list_page.dart
      product_api.dart
  shared/
    widgets/
      primary_button.dart
    utils/
      formatters.dart

Everything about products sits together, so a change to that feature touches one folder. The architecture chapter goes deeper.

Where native settings live #

TaskAndroidiOS
App nameandroid/app/src/main/AndroidManifest.xmlios/Runner/Info.plist
PermissionsAndroidManifest.xmlInfo.plist
App id, minimum OS versionandroid/app/build.gradle.ktsXcode project settings
Launcher iconandroid/app/src/main/res/ios/Runner/Assets.xcassets/

Version control #

Commit lib/, test/, the platform folders, pubspec.yaml, pubspec.lock and analysis_options.yaml. Leave out build/ and .dart_tool/. The generated .gitignore already does this.

Try it yourself #

Move CounterPage from the previous lesson into lib/features/counter/counter_page.dart and import it in main.dart.

Practise in the playground Updated by Santosh Adhikari