Skip to content

Scaffolding a Flutter Modular Monorepo

What you'll learn

  • Generating a complete Flutter monorepo from scratch
  • Configuring variables like state management, networking, and CI provider
  • Understanding the generated workspace structure
  • Running the generated project and verifying the setup

Prerequisites

  • Archipelago CLI installed and authenticated (see Installing & Setting Up)
  • Flutter SDK 3.x installed
  • Familiarity with Flutter project structure

Step 1: Generate the Monorepo

Run the generate command interactively:

bash
archipelago generate flutter_modular_monorepo

The CLI prompts you for each configuration variable. For a typical project, answer like this:

  • appNameMyApp (used for package names and display)
  • organizationMyCompany
  • domaincom (produces com.mycompany.myapp)
  • prefixApp (components become AppButton, AppCard, etc.)
  • gitProvidergithub or gitlab
  • networkLibrarydio (recommended) or http
  • stateManagementbloc, provider, or riverpod

Step 2: Use a Config File for CI

For repeatable, non-interactive generation, create a JSON config:

json
{
  "appName": "Tokopay",
  "organization": "Tokopay",
  "domain": "com",
  "prefix": "Tp",
  "prefixCasing": "pascalCase",
  "gitProvider": "github",
  "networkLibrary": "dio",
  "isUsingWebSocket": false,
  "websocketLibrary": "dart",
  "isUsingFirebase": false,
  "isUsingAnalytics": false,
  "isUsingFeatureFlags": false,
  "stateManagement": "bloc",
  "includeGenerated": false
}

Then run:

bash
archipelago generate flutter_modular_monorepo --config tokopay_config.json

Step 3: Explore the Generated Structure

The brick generates a full Dart workspace:

tokopay/
├── apps/
│   └── tokopay/              # Shell app with two-phase init
│       ├── lib/
│       │   ├── di/injector.dart
│       │   ├── host/initializers/
│       │   ├── router/app_router.dart
│       │   ├── main_development.dart
│       │   └── main_staging.dart
│       └── fastlane/         # iOS/Android build lanes
├── shared/
│   ├── feature_sdk/          # FeatureSDK base class + registry
│   ├── locale_core/          # Shared locale state
│   └── router_registry/      # Route self-registration
├── infrastructure/           # Network, monitoring, analytics SDKs
├── features/                 # Feature modules (auth, home, etc.)
├── packages/                 # UI kit, shared deps
├── devtools/                 # Monorepo toolkit scripts
└── pubspec.yaml              # Workspace root

Step 4: Resolve Dependencies and Run

bash
cd tokopay
dart pub get
cd apps/tokopay
flutter run

The shell app bootstraps all registered FeatureSDKs through the two-phase initialization flow: pre-launch (DI, routes) runs before the first frame, and post-launch (analytics, flags) runs after.

Step 5: Verify the Dual-GetIt Setup

Open apps/tokopay/lib/di/injector.dart. You will see two GetIt instances:

  • Global — SDKs, infrastructure (network, monitoring, analytics)
  • Local — Per-feature registrations (repos, datasources, usecases)

Each feature registers itself via its FeatureSDK, so the shell app never imports feature internals directly.

Key Configuration Choices

VariableEffect
networkLibrary: dioGenerates Dio-based HTTP client with interceptors
networkLibrary: httpGenerates dart:http-based client
isUsingWebSocket: trueAdds WebSocket SDK package to infrastructure
isUsingFirebase: trueIncludes Firebase init in bootstrap
stateManagement: blocGenerates BLoC boilerplate in features
gitProvider: githubCreates .github/workflows/ CI templates
gitProvider: gitlabCreates .gitlab-ci.yml instead

Next Steps

Built by Banua Coder