Skip to content

Generating Features

What you'll learn

  • How the ephemeral config flow works
  • Adding a new feature module to your monorepo
  • Understanding what gets generated and why
  • Registering the feature with the app shell

Prerequisites

How Ephemeral Config Works

When you generate a feature, Archipelago uses an ephemeral configuration flow:

  1. The CLI collects your inputs (feature name, options, dependencies)
  2. A temporary config is built in memory
  3. Mason bricks are invoked with the config
  4. Generated files are written to your project
  5. The config is discarded (not stored anywhere)

This means you can re-generate or update features without worrying about stale config files.

Step 1: Generate a Feature

bash
archipelago generate feature payments

The CLI prompts for:

  • Feature name — Used for package and class naming
  • Include API package? — Yes if other features depend on it
  • Include noop implementation? — Yes for build-time stripping
  • Dependencies — Select from existing features/SDKs

Step 2: Review the Output

A typical feature generates:

packages/features/payments/
├── payments_api/        # Public contracts (if API split selected)
│   ├── lib/
│   │   └── src/
│   │       ├── models/
│   │       └── repositories/
│   └── pubspec.yaml
├── payments_impl/       # Vendor implementation
│   ├── lib/
│   │   └── src/
│   │       ├── datasources/
│   │       ├── repositories/
│   │       └── di/
│   └── pubspec.yaml
└── payments_noop/       # No-op for release stripping (if selected)
    ├── lib/
    └── pubspec.yaml

Step 3: Register the Feature

After generation, register the feature SDK in your app shell:

dart
// apps/my_app/lib/main.dart
void main() async {
  // Pre-launch phase
  PaymentsSDK.register();

  // ... other registrations
  runApp(const MyApp());
}

The feature self-registers its routes, DI bindings, and initialization hooks.

Step 4: Wire Up Dependencies

If your feature depends on other SDKs, the generated DI module handles it:

dart
// payments_impl/lib/src/di/payments_module.dart
class PaymentsModule {
  static void register() {
    final networkSdk = GetIt.I<NetworkSDK>();
    // Register datasources, repos, usecases...
  }
}

When to Use API/Impl Split

ScenarioUse API Split?
Feature consumed by other featuresYes
Might swap vendor implementationYes
Self-contained featureNo
Debug/release behavior differenceUse impl/noop instead

Next Steps

Dive deeper into the architecture patterns in Understanding API/Impl Split.

Built by Banua Coder