Skip to content

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

Step 1: Generate the Feature

From your monorepo root, run:

bash
archipelago generate feature_monorepo_skeleton

Answer the prompts:

  • featureNamePayment (PascalCase, becomes payment in paths)
  • isSharedfalse for a self-contained feature, true if other features depend on it
  • hasBusinessLogictrue to include repos, usecases, and DI layers
  • hasLocaletrue if 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.json

Step 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 files

Step 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());

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

ValueGenerated 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
noneNo state layer generated — preserves the existing ValueNotifier-based presentation shell

Example — generate a feature with a cubit out of the box:

bash
archipelago generate feature_monorepo_skeleton --featureName Payment --stateManagement cubit

Choosing 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

PatternUse When
Single packageFeature is self-contained, no other module needs its contracts
API/Impl splitOther features depend on this feature's types or status
No business logicPure UI feature (e.g., onboarding slides, static about page)
With localeFeature has user-facing strings that need translation

Next Steps

Built by Banua Coder