A smart Flutter project setup saves hours on every feature, release, and handoff. This guide shows a pragmatic scaffold you can adopt today—folders, flavors, env management, lints, tests, and CI—so your app scales without chaos.
Audience: BeginnerTested on: Flutter 3.x, Dart 3.x, macOS 14 / Windows 11, Android 14 / iOS 17
Goals
- One codebase → multiple environments (dev/qa/prod) with reproducible builds.
- Clear folders, predictable naming, and opinionated tooling.
- Quality gates (lints/tests) that won’t slow you down.
Recommended folder structure
lib/
app/ # app root, router, themes, di
features/
auth/
data/ # repositories, data sources
domain/ # entities/use-cases
presentation/ # widgets, state
shared/ # ui kit, utils, services (logger, http, storage)
assets/
images/ fonts/ lottie/
tool/
analysis_options.yaml
env/ # dev.json, qa.json, prod.json (non-secret)
test/ integration_test/
Flavors & environment config
Keep secrets out of source control. Use --dart-define for non-secret config and platform keystores/Keychain for secrets.
# tool/env/dev.json (example; non-secret)
{
"API_BASE_URL": "https://api-dev.example.com",
"FEATURE_FLAGS": "new_ui=true"
}
# Build commands
flutter run --dart-define-from-file=tool/env/dev.json
flutter build apk --release --dart-define-from-file=tool/env/qa.json
flutter build appbundle --release --dart-define-from-file=tool/env/prod.json
iOS/Android “flavors” are optional; many teams simply pass --dart-define-from-file and switch icons/splash via config.
Dependency basics (keep it lean)
- HTTP:
httpordio(choose one). Wrap with a small client for timeouts/retries. - State: Start simple (Provider/Riverpod). Avoid premature architecture bloat.
- Storage:
shared_preferencesfor simple,hivefor structured,flutter_secure_storagefor secrets. - Logging:
loggerwith release-safe filtering and redaction.
Lints you’ll actually keep
Create tool/analysis_options.yaml and include it from the root to share across packages.
# analysis_options.yaml
include: package:flutter_lints/flutter.yaml
analyzer:
language:
strict-inference: true
strict-casts: true
linter:
rules:
always_declare_return_types: true
prefer_final_locals: true
prefer_const_constructors: true
avoid_print: true
# Run
dart analyze
Testing: fast feedback
# Unit & widget tests
flutter test
# Integration (smoke) on device/emulator
flutter drive --profile -t integration_test/smoke_test.dart
Golden tests? Pin fonts/themes to avoid flakiness and store baselines under test/goldens.
Release hardening
# Smaller, debuggable releases
flutter build appbundle --release \
--obfuscate --split-debug-info=out/symbols/$(date +%Y-%m-%d_%H%M%S) \
--dart-define-from-file=tool/env/prod.json
- Keep symbol files for crash mapping.
- Automate icons (
flutter_launcher_icons) and splash (flutter_native_splash).
CI outline (GitHub Actions example)
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: 'stable'
- name: Get deps & analyze
run: |
flutter pub get
dart analyze --fatal-infos --fatal-warnings
- name: Tests
run: flutter test --coverage
- name: Build QA APK
run: flutter build apk --release --split-per-abi \
--dart-define-from-file=tool/env/qa.json
- name: Build Play AAB
run: flutter build appbundle --release \
--dart-define-from-file=tool/env/prod.json \
--obfuscate --split-debug-info=out/symbols/${{ github.run_id }}
Security & pitfalls
- Secrets in git: Never store keys in JSON or code. Use CI secrets & platform keystores.
- Multiple env drifts: Keep one source of truth (the JSON). Don’t fork code per env.
- Measuring in debug: Validate performance in profile/release, not debug.
FAQ
Q: Do I need flavors for everything?
A: Not necessarily. Many teams ship with plain targets and --dart-define-from-file for speed.
Q: Where do I put big one-off scripts?
A: In tool/ with README comments and a Makefile/PowerShell shim if desired.
Conclusion
Start with a lean folder layout, pass environment values via --dart-define, enforce lints/tests, and script your builds. This Flutter project setup scales from the first commit to production without rewrites.
https://docs.flutter.dev/deployment
https://docs.flutter.dev/testing
https://dart.dev/tools/linter-rules
Updated: 2025-10-26


Comment