Feature SDKs
How to add an onboarding flow to a Flutter app
Free Reference for introduction_sdk: every variable, option and package it generates. Command: archipelago generate introduction_sdk
Generate the Introduction SDK, see how it claims the initial route, save completion so users see it once, and customize the pages.
What you'll learn
- Generating the Introduction SDK with the onboarding flow
- Understanding how it claims the initial route
- Saving completion so users see the intro once
- Customizing the pages
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
auth_sdkandhome_sdkgenerated first
The pages call AuthSDK.requireAuthentication() and HomeSDK.goToHome(). The brick does not generate these for you, so a standalone run leaves an unresolved workspace. flutter_modular_monorepo avoids this. It adds auth_sdk and home_sdk when you pick introduction_sdk in starterFeatures.
Step 1: Generate the Introduction SDK
archipelago generate introduction_sdkThe prompts are:
- appName: your app name, for example
MyApp - prefix: the prefix for generated class names
- uiKitPackageName: the UI kit package. It is read from
archipelago.yaml. - isForMonorepo: leave this as
true
Or use a config file:
{
"appName": "MyApp",
"isForMonorepo": true
}archipelago generate introduction_sdk --config intro_config.jsonStep 2: Understand the Generated Structure
The brick makes one flat package. There is no _api and _impl split, because no other feature needs its contract.
features/introduction/
├── lib/src/
│ ├── introduction_sdk.dart # IntroductionSDK and its implementation
│ ├── di/introduction_global_module.dart
│ ├── presentation/
│ │ ├── introduction_shell_page.dart
│ │ ├── welcome_page.dart
│ │ ├── features_page.dart
│ │ └── get_started_page.dart
│ └── router/introduction_router.dart
├── build.yaml
└── pubspec.yamlStep 3: Check the Registration
The post-generation hook adds the package to the workspace and the app pubspec.yaml. It registers IntroductionGlobalModule in lib/di/injector.dart. You write no registration code.
The global module registers IntroductionManifest and IntroductionSDK as a lazy singleton. The manifest claims the initial path /introduction with priority 10:
InitialPathClaim(
priority: 10,
resolve: () => isCompleted() ? null : '/introduction',
)The pages read IntroductionSDK, AuthSDK and HomeSDK from an IntroductionScope widget in the shell page, not from GetIt. Priority 10 is checked first. Onboarding wins until it is completed. The claim reads isCompleted through a provider closure. The SDK is built when the router resolves the initial path.
Step 4: Save Completion
The brick keeps completion in memory only. As generated, users see onboarding on every cold start. Add persistence before you ship.
IntroductionSDKImpl has two TODO(user) comments, in initialize() and in markIntroductionCompleted(). Load and save the flag there, for example through storage_sdk. Take the storage by constructor and pass it from the global module.
Step 5: Complete or Skip the Intro
final sdk = getIt<IntroductionSDK>();
if (!sdk.isCompleted) {
await sdk.launch(context); // replaceAll to the introduction shell
}
sdk.markIntroductionCompleted();
sdk.skipIntroduction(); // calls markIntroductionCompleted()Step 6: Customize the Pages
Replace the placeholder content in welcome_page.dart, features_page.dart and get_started_page.dart. Read tokens from context.colors, context.typography and context.spacing.
Common Customizations
| Customization | Where to Change |
|---|---|
| Number of feature pages | features_page.dart |
| Skip button | welcome_page.dart |
| Branding and assets | The page files and your asset package |
| Completion storage | IntroductionSDKImpl |
| Route priority | The InitialPathClaim in the manifest |
Next Steps
- Set up Auth for the sign-up flow after onboarding
- Configure the UI Kit to theme onboarding pages