Writing the app with mini_app_sdk
A mini app is a Flutter web app inside the host's WebView. It depends on one package,
mini_app_sdk (vendored under packages/), and never touches JavaScript.
Connect once
final sdk = switch (await MiniAppSdk.connect()) {
Ok(:final value) => value,
Err() when kDebugMode => (await LocalHost().connect()).valueOrNull!, // no host: fakes
Err(:final error) => throw StateError('Not inside a host app: $error'),
};
runApp(App(sdk: sdk));
After the handshake, sdk.info (id, name, version, permissions), sdk.host (name, locale…) and
sdk.supports(method) are available. Pass sdk down; do not connect twice.
Errors are values
Every call returns Outcome<T, BridgeError>: Ok(value) or Err(error). Nothing throws across
the bridge. Codes: permissionDenied, methodNotFound, invalidParams, cancelled (the user
dismissed a picker — normal, not a failure), timeout, unavailable, payloadTooLarge,
originNotAllowed, internalError, invalidResponse.
The clients
| Client | Permission | Calls |
|---|---|---|
sdk.app |
none | close(), setTitle(), openExternal(uri), openInAppBrowser(uri, title:); events onResumed, onPaused |
sdk.auth |
auth |
getToken(), getUser(); event onChanged |
sdk.storage |
storage |
get, set, remove, clear, keys — per app, JSON values, key ≤ 128 chars, value ≤ 64 KiB, ≤ 512 keys |
sdk.files |
files |
pick(allowMultiple:), pickImage(source:, maxDimension:, quality:), save(file) — ≤ 10 MiB |
sdk.share |
share |
text(text, subject:), file(MiniAppFile) |
A host may add its own modules; call them with sdk.bridge.invoke<T>('payments.pay', params: {...}, decode: ..., interactive: true) behind a small typed client of your own.
Tests without a host
final host = LocalHost(appName: 'Expense Tracker', permissions: {'auth', 'storage'});
final sdk = (await host.connect()).valueOrNull!;
await tester.pumpWidget(App(sdk: sdk));
host.auth, host.storage, host.files, host.share are the fakes; leave a permission out to
test the denied path. Keep the bridge at the edge of your app (repositories call sdk.*, widgets
never do), and never store tokens yourself.
See the framework, drawn out for how a call travels and why.