Documentation
Integrate the SDK
Use The SDK Entrypoint
Import package:revclust_flutter_sdk/revclust_flutter.dart. Initialize with RevclustConfig(...). Keep the returned Revclust client and reuse it later for capture, status, and upload checks.
Read The Runtime Values
Do not hardcode the SDK key in app code. Read it from the build and fail fast if it is missing.
import "package:revclust_flutter_sdk/revclust_flutter.dart";
const String revclustProjectKey = String.fromEnvironment(
"REVCLUST_PROJECT_KEY",
);
String requireRevclustProjectKey() {
if (revclustProjectKey.isEmpty) {
throw StateError("Missing REVCLUST_PROJECT_KEY");
}
return revclustProjectKey;
}
For a first local check, the simplest run command is:
flutter run \
--dart-define=REVCLUST_PROJECT_KEY=rpk_...
If your app already has flavors or CI-managed build injection, keep using that system. The important part is that the app passes the right SDK key into the projectKey field in RevclustConfig(...).
Initialize Once
Call Revclust.initialize(...) once during app startup and keep the returned client. Pass the rpk_... SDK key copied from Apps as projectKey. Do not initialize the SDK again with a different config in the same app process.
After initialization returns, check revclust.status. ready means hosted bootstrap is usable. degraded or uploadBlocked can still queue local captures, but upload is not ready. misconfigured or notProvisioned means setup must be corrected before you continue.
import "package:flutter/widgets.dart";
import "package:revclust_flutter_sdk/revclust_flutter.dart";
Future<Revclust> configureRevclust() async {
WidgetsFlutterBinding.ensureInitialized();
final Revclust revclust = await Revclust.initialize(
RevclustConfig(
projectKey: requireRevclustProjectKey(),
),
);
revclust.setStateSnapshotProvider(
() => const RevclustStateSnapshot(
appState: <String, Object?>{
"screen": "checkout_confirmation",
},
dataState: <String, Object?>{
"order_ref": "ord_ref_7d82b1",
},
),
);
return revclust;
}
Add Optional Build Metadata
Once the first capture works, pass release/build metadata from your existing build or CI system so captured packs identify the release that produced the incident.
const String revclustAppVersion = String.fromEnvironment(
"REVCLUST_APP_VERSION",
);
const String revclustBuild = String.fromEnvironment("REVCLUST_BUILD");
const String revclustGitSha = String.fromEnvironment("REVCLUST_GIT_SHA");
String? optionalBuildValue(String value) {
if (value.isEmpty) {
return null;
}
return value;
}
final Revclust revclust = await Revclust.initialize(
RevclustConfig(
projectKey: requireRevclustProjectKey(),
appVersion: optionalBuildValue(revclustAppVersion),
build: optionalBuildValue(revclustBuild),
gitSha: optionalBuildValue(revclustGitSha),
releaseStage: RevclustAppReleaseStage.production,
),
);
releaseStage, appVersion, build, and gitSha are reproduction metadata. They do not route the SDK to Revclust staging or local infrastructure.
Keep One Shared Client
Do not scatter initialization and capture calls across unrelated widgets. Put the client in one shared startup or service layer, initialize it there, and pass it into the first flow.
final class RevclustRuntime {
Revclust? _client;
Revclust get client => _client!;
Future<void> initialize() async {
if (_client != null) {
return;
}
final Revclust revclust = await configureRevclust();
_client = revclust;
}
}
In a Flutter app, that usually means main(), a top-level startup layer, or the DI container that owns the first flow. Later flow code should receive this runtime or the Revclust client it owns.
Add A Small State Snapshot
setStateSnapshotProvider(...) takes a synchronous callback that returns RevclustStateSnapshot. Keep appState and dataState small, privacy-safe, and useful for one incident. Screen name, step name, and a few safe IDs are usually enough.
Keep Automatic Hooks Off By Default
For the default hosted Flutter setup, leave enableDioCapture(...) and
enableUnhandledExceptionCapture() off.
The default hosted path is:
- initialize the SDK once
- register a small state snapshot
- wire one explicit
captureInvariantFailure(...)point in host code
Do not treat the automatic hooks as part of the default first-pass setup.
Stop If Initialization Fails
Revclust.initialize(...) can throw if local capture setup fails. Catch that failure at app startup, log it clearly, and stop there until the runtime is healthy.
try {
await revclustRuntime.initialize();
} on StateError catch (error, stackTrace) {
debugPrint("Revclust initialization failed: $error");
FlutterError.reportError(
FlutterErrorDetails(exception: error, stack: stackTrace),
);
rethrow;
}
Integration Checklist
Before you move on, confirm that Revclust.initialize(...) returns a client,
the build is injecting the right SDK key, revclust.status is ready, one
state snapshot provider is registered, and one explicit capture point is
chosen for the first flow. Then move on to the first incident.
Continue to Trigger Your First Incident.