Revclust
DocsPricing
Log inStart free
DocsPricingLog inStart free

Start Here

  • Overview
  • Access and Setup
  • Getting Started

Integration

  • Integrate the SDK
  • Trigger Your First Incident

Verification

  • Verify and Observe

Viewer

  • Viewer Workflow

Help

  • Troubleshooting

Reference

  • SDK Reference

Documentation

Integrate the SDK

Initialize the SDK once, add a small state snapshot, and wire the app for the first flow.

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.

On this page

  1. Use The SDK Entrypoint
  2. Read The Runtime Values
  3. Initialize Once
  4. Add Optional Build Metadata
  5. Keep One Shared Client
  6. Add A Small State Snapshot
  7. Keep Automatic Hooks Off By Default
  8. Stop If Initialization Fails
  9. Integration Checklist
TermsPrivacy Policy