Generating a Feature Module
What you'll learn
- Creating a new feature module inside your monorepo
- Choosing between single-package and API/Impl split patterns
- Wiring the feature into the shell app via FeatureSDK
- Adding routes, DI, and business logic layers
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
- Understanding of clean architecture layers (data, domain, presentation)
Step 1: Generate the Feature
From your monorepo root, run:
archipelago generate feature_monorepo_skeletonAnswer the prompts:
- featureName —
Payment(PascalCase, becomespaymentin paths) - isShared —
falsefor a self-contained feature,trueif other features depend on it - hasBusinessLogic —
trueto include repos, usecases, and DI layers - hasLocale —
trueif the feature manages its own translations
Step 2: Non-Interactive Config
{
"featureName": "Payment",
"isShared": false,
"hasBusinessLogic": true,
"hasLocale": true,
"includeGenerated": false
}archipelago generate feature_monorepo_skeleton --config payment_config.jsonStep 3: Single-Package Structure
When isShared: false, you get a self-contained feature:
features/
└── payment/
├── lib/
│ ├── payment.dart # Barrel export
│ └── src/
│ ├── payment_sdk.dart # FeatureSDK implementation
│ ├── data/
│ │ ├── datasources/
│ │ │ ├── local/
│ │ │ └── remote/
│ │ ├── models/
│ │ └── repositories/
│ ├── di/
│ │ ├── injector.dart
│ │ ├── payment_global_module.dart
│ │ └── payment_local_module.dart
│ ├── domain/
│ │ ├── entities/
│ │ ├── repositories/
│ │ └── usecases/
│ ├── presentation/
│ │ ├── payment_shell_page.dart
│ │ └── ui/pages/
│ └── router/
│ └── payment_router.dart
└── l10n/ # Localization filesStep 4: API/Impl Split Pattern
Set isShared: true when the feature exposes contracts to other features (e.g., auth status checks). This generates two packages:
features/
├── payment_api/ # Contracts only (FeatureSDK, entities)
│ └── lib/src/
│ └── payment_sdk.dart
└── payment_impl/ # Full implementation
└── lib/src/
├── payment_sdk_impl.dart
├── data/
├── di/
├── domain/
├── presentation/
└── router/Other features depend on payment_api only, never on payment_impl. The shell app wires the impl at the DI level.
Step 5: Register the Feature
The generated PaymentSdk class extends FeatureSDK and self-registers. Open it to see:
class PaymentSdk extends FeatureSDK {
@override
Future<void> preLaunch() async {
// Register DI modules
PaymentGlobalModule().init();
PaymentLocalModule().init();
}
@override
List<RouteBase> get routes => PaymentRouter.routes;
}Add it to the feature registry in the shell app's bootstrap.dart:
FeatureRegistry.register(PaymentSdk());State Management Variable
The feature_monorepo_skeleton brick accepts a stateManagement variable that generates a state management skeleton alongside the feature module structure.
Options: bloc / cubit / riverpod / provider / none
| Value | Generated files |
|---|---|
cubit | _cubit.dart, _state.dart, _cubit_test.dart |
bloc | _bloc.dart, _event.dart, _state.dart, _bloc_test.dart |
riverpod | _notifier.dart, _state.dart, _notifier_test.dart |
provider | _notifier.dart, _notifier_test.dart |
none | No state layer generated — preserves the existing ValueNotifier-based presentation shell |
Example — generate a feature with a cubit out of the box:
archipelago generate feature_monorepo_skeleton --featureName Payment --stateManagement cubitChoosing none leaves the default ValueNotifier in the presentation shell untouched. This is the safest choice when you want to add state management later or prefer to manage it yourself.
For more detail on each variant, see the state_management brick tutorial.
When to Use Each Pattern
| Pattern | Use When |
|---|---|
| Single package | Feature is self-contained, no other module needs its contracts |
| API/Impl split | Other features depend on this feature's types or status |
| No business logic | Pure UI feature (e.g., onboarding slides, static about page) |
| With locale | Feature has user-facing strings that need translation |
Next Steps
- Set up authentication with the Auth SDK brick
- Learn about the monitoring SDK and the noop pattern