Project Structure
Anatomy of a Flutter project: pubspec.yaml, lib/, assets, platforms, run + build + flavours. The structure underneath flutter create.
Flutter — project anatomy
EXAMPLE
# ===== After 'flutter create my_app' =====
# my_app/
# pubspec.yaml dependencies + assets + metadata
# lib/
# main.dart entry: runApp(MyApp())
# test/
# widget_test.dart sample widget test
# android/ Android Studio project
# ios/ Xcode project
# web/ index.html + manifests
# macos/ windows/ linux/ desktop hosts
# .dart_tool/ cache (gitignored)
# build/ build outputs (gitignored)
# ===== pubspec.yaml =====
name: my_app
description: A new Flutter project.
version: 1.0.0+1 # <semver>+<build_number>
environment:
sdk: '>=3.4.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
provider: ^6.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
flutter:
uses-material-design: true
assets:
- assets/images/
fonts:
- family: Inter
fonts:
- asset: assets/fonts/Inter-Regular.ttf
- asset: assets/fonts/Inter-Bold.ttf
weight: 700
# After editing:
flutter pub get
# ===== lib/ layout (small project) =====
# lib/
# main.dart
# app.dart MaterialApp + theme + router
# theme.dart
# features/
# orders/
# order.dart model
# orders_provider.dart state
# orders_page.dart UI
# shared/
# widgets/
# utils/
# ===== A run-friendly 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) => MaterialApp(
title: 'My App',
theme: ThemeData(useMaterial3: true),
home: const HomePage(),
);
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Home')),
body: const Center(child: Text('Hello, Flutter')),
);
}
# ===== Run + build =====
flutter run # to current device
flutter run -d chrome # web
flutter run -d macos # desktop
flutter run --release # release build, even in dev
flutter build apk --release # Android APK
flutter build appbundle --release # AAB for Play Store
flutter build ipa --release # iOS IPA (macOS only)
flutter build web --release # static web bundle
# ===== Flavours / environments =====
# Define in android/app/build.gradle + ios/Runner.xcodeproj:
# prod, staging, dev
# Then:
flutter run --flavor staging -t lib/main_staging.dart
# Or simpler: --dart-define
flutter run --dart-define=API=https://staging.example.com
const apiUrl = String.fromEnvironment('API', defaultValue: 'http://localhost:3000');
# ===== Useful CLI =====
flutter clean # nuke build/ + .dart_tool/
flutter pub get / upgrade
flutter pub outdated
flutter analyze # lint + type check
dart format . # format
# ===== Patterns to internalise =====
# - One state-management library per app (Provider, Riverpod, Bloc)
# - --dart-define for environment config; do not hardcode
# - flutter analyze in CI as a required check
# - lib/features/<area>/ over a 'screens' grab-bag
# ===== Pitfalls =====
# - Mismatched Flutter + Dart SDK constraints in pubspec
# - Mixing UI + business logic in one widget tree
# - Forgetting to include assets/fonts in pubspec after adding files
# - Building release APK without signing config -> can't ship
Why it matters
A Flutter project is pubspec.yaml + lib/ + per-platform host directories. Pin SDK constraints, declare assets + fonts in pubspec, organise lib by feature, and lean on --dart-define for environments. The same project ships to six platforms with the same conventions; the discipline is keeping the lib tree tidy.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// myapp/ // lib/ main.dart, widgets/, screens/ // test/ unit + widget tests // android/ ios/ web/ // pubspec.yaml deps, assets, versionTry it Yourself »
Discussion
Loading…