Flutter monorepo template with clean architecture, modular packages, and one-command project initialization.
- FVM — Flutter version manager
- Melos — monorepo package orchestration
- Make — build automation
- CocoaPods — iOS dependency manager
- Xcode — iOS builds
- Android SDK — Android builds
Clone the repo, then run the init script:
scripts/init.shThe script prompts for an app display name and two bundle IDs (Android and iOS), renames all platform
identifiers across the project, and runs make init to bootstrap the workspace.
Run scripts/init.sh --help for details.
apps/
basic/ # GMS production target (main.dart only)
debug/ # Debug target with debug screen (main.dart + app.dart)
packages/
core/ # Environment config, Urls, BuildType, TestEnvDetector
util/ # Closures, string/iterable extensions
data/ # Infrastructure (analytics, api, database, location, network, push, storage)
uikit/ # Reusable UI widget library
features/ # Feature packages (app, common, debug, device_settings, haptics, splash, theme)
Each feature under packages/features/ follows clean architecture with sub-packages:
domain/— entities, repository interfaces, BLoCs (@freezed events/states)data/— repository and service implementationsdi/— DI scope (yx_scope containers, holders, registrars)presentation/— UI components, layouts, feature entry
- DI (yx_scope) — Root scope
AppScopeContainerinpackages/features/app/target/. Feature scopes useChildScopeContainer,ChildScopeHolder, andDependenciesRegistrarpattern. - State Management —
bloc/flutter_blocwith@freezedevents and states. BLoCs created in DI scopes, provided viaBlocProvider.value. - UI —
Component<VM, L>(StatefulWidget + ViewModel) paired withLayout<VM>(pure rendering). Screens wrapped byFeatureEntryfor DI scope creation. - Routing —
AppRouterusingNamedRouteDef— no code generation. Cross-feature navigation viacontext.router.pushPath(...).
| Command | Description |
|---|---|
make init |
Full setup: pub get, codegen, codegen-assets, format |
make get |
Just fvm flutter pub get |
make codegen |
Run build_runner across all packages (freezed, etc.) |
make codegen-assets |
Run fluttergen in packages/features/app/assets/ |
make intl-with-format |
Regenerate l10n files and format |
make format |
Format all packages (line length 120) |
make test |
Run all tests |
make clean |
Remove .dart_tool and flutter clean |
make force-clean |
Clean + pub cache repair |
fvm flutter run --flavor dev -t apps/basic/lib/main.dart # basic target
fvm flutter run --flavor dev -t apps/debug/lib/main.dart # debug target| I want to... | Put it in... |
|---|---|
| Add a new feature | packages/features/<name>/ with domain/, data/, di/, presentation/ sub-packages |
| Add a new BLoC | packages/features/<feature>/domain/ with @freezed events/states |
| Add a shared UI widget | packages/uikit/ |
| Add an API client | packages/data/api/ |
| Add a utility extension | packages/util/ |
| Add a data sub-package | packages/data/<name>/ |
Templates in tools/mason/ generate boilerplate:
- feature — full feature package with domain/data/di/presentation
- bloc — BLoC with @freezed events and states
- screen — Component + Layout pair
- widget — reusable widget
- Create the package directory under
packages/ - Add it to the
workspace:list in rootpubspec.yaml - Run
make get