Skip to main content
Use this page when you need the exact Flutter SDK behavior and option surface. For setup instructions, start with the Flutter SDK guide.

Support matrix

AreaFlutter SDK behavior
Packagelucent_flutter
Supported platformsiOS and Android
Deferred platformsFlutter Web and macOS are not in the MVP
Replay modeScreenshot-mode mobile replay
Backend classificationlucent-flutter maps to mobile_flutter
iOS packagingCocoaPods is verified
Android packagingFlutter plugin with Android min SDK 23; release apps need android.permission.INTERNET
Example appsdk-flutter-lucent/example in the SDK repo

Replay envelope

Flutter replay is always sent as mobile screenshot replay:
The SDK captures a masked RepaintBoundary image from LucentWidget, encodes it as a mobile screenshot wireframe, and posts batches to /api/sdk/replay. The backend classifies these sessions as mobile_flutter.

Persistence and retry

Replay batches are persisted on disk before upload on iOS and Android. Failed uploads remain queued for retry.
LimitValue
Maximum queued batch files100
Maximum queued bytes50 MB
Maximum queued age7 days
Android also persists current in-memory replay events between flushes, so active events can survive a process restart before they become an upload batch. flush() is best effort. If the network request fails, the persisted batch stays queued and is retried later. When LucentWidget sees the app pause or become inactive, it emits Application Backgrounded and requests a flush. When the app resumes, it emits Application Became Active.

Configuration

Pass LucentConfig to Lucent().setup(...).

Core

OptionDefaultNotes
publicKeyRequiredYour Lucent public key. Safe to expose in client code.
ingestBaseUrlhttps://ingest-api.lucenthq.comOverride only for self-hosted or internal testing.
environmentLucentEnvironment.productionUse staging or development for non-production apps.
autoStarttrueSet to false when you need to wait for consent.
remoteConfigtrueFetches /api/sdk/init before auto-starting when enabled.
sessionReplaySampleRate1Clamped between 0 and 1.
When remoteConfig is enabled, native replay waits for /api/sdk/init before auto-starting. If the request fails, the SDK falls back to local config. Remote config can disable recording, override session sample rate, update batching limits, change minimumDuration, toggle log/network telemetry, and replace eventTriggers.

Privacy

OptionDefaultNotes
privacy.maskAllTexttrueMasks Text, RichText, and editable text widgets by default.
privacy.maskAllImagestrueMasks rendered image widgets by default.
LucentMask forces masking for a subtree. LucentNoMask makes its subtree visible, so keep sensitive widgets outside any LucentNoMask region.
Flutter does not have browser-style CSS selectors. Review any LucentNoMask subtree carefully before shipping.

Capture

OptionDefaultCaptures
capture.touchestruePointer-down coordinates and $touch events.
capture.appLifecycletrueApplication Opened, Application Became Active, and Application Backgrounded.
capture.errorstrueFlutter framework errors.
capture.unhandledRejectionstruePlatformDispatcher async errors.
capture.nativeCrashestrueNative uncaught exceptions on next launch.
capture.logstruedebugPrint, print inside runZoned, and manual logs.
capture.networktruedart:io network breadcrumbs inside runZoned and manual network breadcrumbs.

Batching

OptionDefaultNotes
batching.flushInterval10 secondsNative flush loop interval.
batching.maxEventsPerBatch500Reaching this triggers a flush.
batching.maxBatchBytes1048576Reaching this triggers a flush.
Native code clamps flush interval, event count, and byte limits to bounded ranges so misconfiguration does not create extremely small or huge batches.

Replay

OptionDefaultNotes
replay.minimumDurationDuration.zeroFinal flushes shorter than this are dropped.
replay.screenshotThrottle1 secondHow often LucentWidget attempts a screenshot.
replay.screenshotBackgroundCapturefalseScreenshots stop while the app is backgrounded by default.
replay.eventTriggers[]When set, recording starts after one of these events is tracked.
snapshotMode is not configurable. It is always screenshot.

Metadata and properties

OptionEvent property
metadata.app$app_name
metadata.namespace$app_namespace
metadata.version$app_version
metadata.build$app_build
metadata.releaserelease
metadata.propertiesMerged into event metadata
Use Lucent().setSessionProperties(...) and Lucent().setUserProperties(...) when values change during a session. The native payload also includes common mobile context: userAgent, language, snapshotSource, snapshotLibrary, snapshotMode, os, deviceType, and environment.

Public API

MethodUse for
Lucent().setup(config)Initialize the SDK and native modules.
Lucent().stop()Stop native recording, uninstall Dart hooks, and perform a final native flush.
Lucent().track(name, properties?)Capture a custom event.
Lucent().identify(user)Associate future events with a known user.
Lucent().resetIdentity()Clear the known user and generate a new anonymous ID.
Lucent().screen(name, properties?)Emit $screen and update replay screen context.
Lucent().setSessionProperties(properties)Attach session-level properties.
Lucent().setUserProperties(properties)Attach user-level properties.
Lucent().captureLog(message, level, properties)Capture a manual log breadcrumb.
Lucent().captureNetwork(...)Capture a manual network breadcrumb.
Lucent().captureNetworkRequest(...)Wrap an async request and capture timing/status.
Lucent().captureException(error, stackTrace?, properties?)Capture a handled exception.
Lucent().addExceptionStep(message, properties?)Add an exception breadcrumb.
Lucent().startSessionRecording(resumeCurrent: true)Resume screenshot replay.
Lucent().stopSessionRecording()Pause screenshot replay and final flush.
Lucent().isSessionReplayActive()Check whether replay is currently active.
Lucent().flush(finalFlush: false)Flush queued events. Set finalFlush: true for a final flush.
Lucent().getSessionInfo()Read sessionId, windowId, and recording state.
Lucent().runZoned(body, onError?)Capture print, async errors, and dart:io network inside a zone.
getSessionInfo() returns sessionId, windowId, and recordingEnabled. Use runZoned(..., onError: handler) if your app already has its own top-level async error handler. LucentObserver accepts two optional callbacks:
CallbackUse for
nameExtractor(RouteSettings settings)Convert route settings into a screen name. Defaults to settings.name.
routeFilter(Route<dynamic>? route)Decide which routes should emit screens. Defaults to route is PageRoute.
For routers that do not expose named PageRoutes, call Lucent().screen(...) from your router listener instead.

Network privacy

Automatic network capture is limited to dart:io HttpClient traffic created inside Lucent().runZoned(...). Other HTTP clients need a wrapper or interceptor that calls captureNetworkRequest or captureNetwork. Lucent captures:
FieldCaptured
HTTP methodYes
URL origin and pathYes
URL user info, query, and fragmentNo
Status codeYes, when available
DurationYes, when available
Transfer sizeYes, when available
Request headersNo
Response headersNo
Request bodyNo
Response bodyNo
Because headers and bodies are not captured, there are no per-field masking rules for them. Sanitize URLs before manual capture if a path segment contains sensitive data.

Error and crash behavior

Error sourceBehavior
Flutter framework errorsCaptured through FlutterError.onError when capture.errors is enabled.
Async platform errorsCaptured through PlatformDispatcher.instance.onError when capture.unhandledRejections is enabled.
Handled exceptionsCapture manually with Lucent().captureException(...).
Native uncaught exceptionsStored synchronously and emitted as $native_crash on the next launch.
Native crash delivery is best effort. If the process cannot write the pending crash payload before termination, there may be no next-launch crash event.

Parity checklist

CapabilityFlutter SDKNotes
iOS replaySupportedScreenshot-mode mobile replay.
Android replaySupportedScreenshot-mode mobile replay.
Flutter Web replayDeferredNo web/canvas capture path in the MVP.
Root replay wrapperSupportedUse LucentWidget.
Route trackingSupportedUse LucentObserver or Lucent().screen(...).
Custom eventsSupportedUse Lucent().track(...).
Identify/resetSupportedUse LucentUser and resetIdentity.
Touch captureSupportedPointer-down coordinate events.
Privacy defaultsSupportedText, inputs, and images mask by default.
LogsSupporteddebugPrint, print in runZoned, and manual logs.
Network breadcrumbsSupporteddart:io in runZoned plus manual APIs.
Handled errorsSupportedcaptureException and exception steps.
Native crashesSupportedNext-launch $native_crash, best effort.
Persistent replay queueSupportediOS and Android batch queues with bounded retention.
Android current-event persistenceSupportedCurrent events persist between flushes.
Remote configSupported/api/sdk/init when enabled.
Event-triggered replaySupportedLucentReplayConfig.eventTriggers.
CocoaPodsSupportedVerified iOS packaging path.
Swift Package ManagerDeferredUse CocoaPods for the MVP.

Not in the Flutter MVP

These browser or React Native capabilities are not available in lucent_flutter 0.1.0:
CapabilityStatus
Flutter Web replayDeferred until a web/canvas capture path exists.
CSS selector privacy rulesNot applicable to Flutter widget trees. Use LucentMask and LucentNoMask.
networkIgnoreUrlsNot exposed. Sanitize URLs manually before manual capture if needed.
Console level filteringNot exposed. debugPrint, zoned print, and manual logs use the configured capture toggle.
Rage-click and dead-click detectionBrowser-only today. Flutter touch capture is coordinate-level.
Alias/group APIsNot in the Flutter MVP.
Persistent super-property registryNot in the Flutter MVP. Use metadata, session properties, and user properties.
Source maps or native symbolicationExternal to the Flutter SDK docs today.
Expo/Metro toolingReact Native only.

Troubleshooting

SymptomCheck
No replay appearsConfirm LucentWidget wraps the app root and sessionReplaySampleRate is greater than 0.
No screen namesAdd named routes, customize LucentObserver, or call Lucent().screen(...) manually.
print logs are missingMake sure runApp runs inside Lucent().runZoned(...).
Network calls are missingConfirm the client uses dart:io inside runZoned, or add manual/interceptor capture.
iOS build fails around podsRun flutter pub get, then cd ios && pod install.
iOS SPM warnings appearUse CocoaPods for the MVP; Swift Package Manager support is deferred.
A physical iOS device will not runEnable Developer Mode and trust the development certificate/device pairing.
Android release uploads failAdd <uses-permission android:name="android.permission.INTERNET" /> to android/app/src/main/AndroidManifest.xml.
Android device install failsConfirm USB debugging is enabled and the device trusts the development machine.
Replay is too sparseLower replay.screenshotThrottle, but watch bandwidth and battery use.