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:
bash
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
json
{
"featureName": "Payment",
"isShared": false,
"hasBusinessLogic": true,
"hasLocale": true,
"includeGenerated": false
}bash
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:
dart
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:
dart
FeatureRegistry.register(PaymentSdk());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