> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lucenthq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter SDK

> Install lucent_flutter and capture mobile session replay, events, logs, network breadcrumbs, and errors.

Lucent's first-party Flutter SDK is published as `lucent_flutter`. The MVP
supports iOS and Android. Flutter Web is deferred because Flutter Web needs a
separate web capture path, while this SDK sends screenshot-mode mobile replay.

## Requirements

* Flutter `>=3.27.0`
* Dart `>=3.6.0`
* iOS `13.0` or later
* Android min SDK `23` or later
* A Lucent public key (`luc_pk_...`)

## Install

`lucent_flutter` is not published on pub.dev yet. Until `0.1.0` is published,
install it from the Lucent monorepo or from a local SDK checkout.

<CodeGroup>
  ```yaml Git theme={null}
  dependencies:
    lucent_flutter:
      git:
        url: https://github.com/lucent-ai/mono-lucent.git
        path: sdk-flutter-lucent
        ref: <commit-or-tag>
  ```

  ```yaml Local theme={null}
  dependencies:
    lucent_flutter:
      path: ../mono-lucent/sdk-flutter-lucent
  ```
</CodeGroup>

After the package is published to pub.dev, use the normal hosted package
dependency:

```yaml theme={null}
dependencies:
  lucent_flutter: ^0.1.0
```

Then fetch dependencies:

```bash theme={null}
flutter pub get
```

For iOS, use the standard Flutter CocoaPods flow:

```bash theme={null}
cd ios
pod install
```

For Android release builds, make sure your app manifest allows network access.
Flutter debug and profile builds may add this automatically, but release apps
should include it explicitly in `android/app/src/main/AndroidManifest.xml`.

```xml theme={null}
<manifest>
  <uses-permission android:name="android.permission.INTERNET" />
</manifest>
```

<Note>
  CocoaPods is the verified iOS packaging path for the MVP. Swift Package
  Manager support is deferred because Flutter can generate a package identity
  from the local SDK directory that differs from the pub package name.
</Note>

## Quick start

Set up Lucent before `runApp`, then wrap your app in `LucentWidget`.

```dart theme={null}
import 'package:flutter/material.dart';
import 'package:lucent_flutter/lucent_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Lucent().setup(
    const LucentConfig(
      publicKey: 'luc_pk_...',
      metadata: LucentMetadataConfig(
        app: 'Acme Mobile',
        namespace: 'com.acme.mobile',
        version: '1.2.3',
        build: '123',
        release: '1.2.3+123',
      ),
    ),
  );

  Lucent().runZoned(() {
    runApp(const LucentWidget(child: MyApp()));
  });
}
```

`LucentWidget` captures screenshot-mode replay, touch events, and app lifecycle
events. Keep it near the root of the app so remounts do not reset the replay
surface.

## Screen tracking

Add `LucentObserver()` to your `MaterialApp` navigator observers to emit
`$screen` events and update the replay URL.

```dart theme={null}
MaterialApp(
  navigatorObservers: [LucentObserver()],
  routes: {
    '/': (_) => const HomeScreen(),
    '/checkout': (_) => const CheckoutScreen(),
  },
)
```

If your router does not use named `PageRoute`s, call `Lucent().screen(...)`
from your route listener.

```dart theme={null}
await Lucent().screen('checkout', {'step': 'payment'});
```

You can also customize the observer for apps that need custom route names or
route filtering.

```dart theme={null}
LucentObserver(
  nameExtractor: (settings) => settings.name ?? 'unknown',
  routeFilter: (route) => route is PageRoute,
)
```

## Identify users

Sessions start with a generated anonymous ID. Call `identify` when you know the
user, and call `resetIdentity` on sign out.

```dart theme={null}
await Lucent().identify(
  const LucentUser(
    id: 'user_123',
    email: 'ada@example.com',
    name: 'Ada Lovelace',
    properties: {'plan': 'pro'},
  ),
);

await Lucent().setUserProperties({'role': 'admin'});
await Lucent().setSessionProperties({'checkoutExperiment': 'variant_a'});
await Lucent().resetIdentity();
```

## Track events

Use `track` for custom events. Event properties also receive metadata from
`LucentMetadataConfig`.

```dart theme={null}
await Lucent().track('checkout_tapped', {
  'plan': 'pro',
  'source': 'pricing',
});
```

## Control recording

Replay starts automatically by default when the session is sampled in. You can
pause, resume, flush, and inspect the current session.

```dart theme={null}
await Lucent().stopSessionRecording();
await Lucent().startSessionRecording(resumeCurrent: true);
await Lucent().flush();
await Lucent().flush(finalFlush: true);

final info = await Lucent().getSessionInfo();
debugPrint(info?.sessionId);
```

Call `Lucent().stop()` when you need to tear down the SDK. It stops native
recording, clears installed Dart hooks, and performs a final native flush.

Use `autoStart: false` or `LucentReplayConfig.eventTriggers` when you need to
wait for consent or only record after specific events.

```dart theme={null}
await Lucent().setup(
  const LucentConfig(
    publicKey: 'luc_pk_...',
    autoStart: false,
    replay: LucentReplayConfig(
      eventTriggers: ['checkout_tapped'],
    ),
  ),
);
```

## Privacy masking

Flutter replay is privacy-first. Text, text inputs, and images are masked by
default. Wrap extra-sensitive regions in `LucentMask`, and wrap safe public
regions in `LucentNoMask`.

```dart theme={null}
const LucentMask(
  child: PaymentCardForm(),
);

const LucentNoMask(
  child: Text('Public status: ready'),
);
```

`LucentNoMask` opts the subtree into replay visibility, so only use it for UI
that is safe to show in a session replay.

## Logs

When `capture.logs` is enabled, Lucent captures Flutter `debugPrint` output.
Wrapping `runApp` in `Lucent().runZoned(...)` also captures `print(...)`.

```dart theme={null}
Lucent().runZoned(() {
  print('App started');
  runApp(const LucentWidget(child: MyApp()));
});

await Lucent().captureLog(
  'Checkout validation failed',
  level: 'warn',
  properties: {'field': 'zip'},
);
```

## Network breadcrumbs

When `capture.network` is enabled, `Lucent().runZoned(...)` installs a
zone-scoped `dart:io` `HttpClient` wrapper. It captures method, sanitized URL,
status, duration, and transfer size for requests made inside the zone.

```dart theme={null}
Lucent().runZoned(() {
  runApp(const LucentWidget(child: MyApp()));
});
```

For clients that do not use `dart:io`, call `captureNetworkRequest` from your
HTTP wrapper or interceptor.

```dart theme={null}
final response = await Lucent().captureNetworkRequest<Response>(
  method: 'GET',
  url: 'https://api.example.com/products?token=secret',
  request: () => client.get('/products'),
  status: (response) => response.statusCode,
  transferSize: (response) => response.bodyBytes.length,
);
```

You can also send a manual network breadcrumb.

```dart theme={null}
await Lucent().captureNetwork(
  method: 'POST',
  url: 'https://api.example.com/checkout',
  status: 200,
  durationMs: 184,
);
```

Lucent strips URL user info, query strings, and fragments before upload.
Request bodies, response bodies, and headers are not captured.

## Errors and crashes

Lucent captures Flutter framework errors and `PlatformDispatcher` async errors
when the corresponding capture options are enabled. Use `captureException` for
handled exceptions and `addExceptionStep` for lightweight breadcrumbs.

```dart theme={null}
try {
  await checkout();
} catch (error, stackTrace) {
  await Lucent().addExceptionStep('Checkout failed after payment tap');
  await Lucent().captureException(error, stackTrace: stackTrace);
  rethrow;
}
```

Native uncaught exceptions are stored synchronously and emitted as
`$native_crash` on the next launch.

If your app already has a top-level async error handler, pass it to
`runZoned`.

```dart theme={null}
Lucent().runZoned(
  () => runApp(const LucentWidget(child: MyApp())),
  onError: (error, stackTrace) {
    // Forward to your existing crash reporter.
  },
);
```

## Example app

The SDK package includes an example app that exercises setup, `LucentWidget`,
`LucentObserver`, masking, custom events, manual network breadcrumbs, handled
exceptions, and flush.

```bash theme={null}
cd sdk-flutter-lucent/example
flutter pub get
flutter run
```

## Next steps

* [Flutter support reference](/sdk/flutter-reference) - options, replay
  envelope, persistence, limitations, and troubleshooting.
* [Replay endpoint](/api-reference/endpoint/replay) - ingest payload schema.
