friction_sdk 0.0.4 copy "friction_sdk: ^0.0.4" to clipboard
friction_sdk: ^0.0.4 copied to clipboard

Zero-config friction capture, voice-AI feedback, and auto-ticketing for Flutter apps. The AI knows what broke because it watched it break.

friction_sdk #

Zero-config friction capture and auto-ticketing for Flutter apps. The AI knows what broke because it watched it break.

friction_sdk is the Flutter client for Friction. Drop it into your app and a floating widget appears whenever a user hits a friction signal — a failed request, an uncaught exception, rage clicks. The user is asked what went wrong, runtime context is captured automatically, and a developer-grade ticket lands in your GitHub repo seconds later.

You upload no docs, no Swagger files, no repo index. Drop in an AppId and ship.

Install #

dependencies:
  friction_sdk: ^0.0.1

Platform setup (required for voice) #

iOS — add to ios/Runner/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>Friction asks for the microphone so you can tell us what went wrong using voice.</string>

Android — add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>

macOS desktop — add to both macos/Runner/DebugProfile.entitlements and Release.entitlements:

<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>

Without these the SDK falls back to text-only feedback automatically — no crash.

Quick start #

import 'package:flutter/material.dart';
import 'package:friction_sdk/friction_sdk.dart';

Future<void> main() async {
  await Friction.init(appId: 'pk_live_YOUR_APP_ID');

  runApp(
    FrictionScope(
      child: MaterialApp(
        navigatorObservers: [FrictionRouteObserver()],
        home: const HomePage(),
      ),
    ),
  );
}

Using MaterialApp.router / go_router #

MaterialApp.router has no navigatorObservers parameter — attaching one there is a compile error. Instead, add the observer to your GoRouter (it forwards observers to its internal Navigator):

final appRouter = GoRouter(
  observers: [FrictionRouteObserver()],
  routes: [ /* ... */ ],
);

Then wrap the app in FrictionScope as usual and pass routerConfig: appRouter to MaterialApp.router. Route tracking (which powers the AI's "I see you're on the checkout screen" opener) works the same way.

That's it. The SDK will now:

  • Catch uncaught exceptions (Flutter framework + Dart isolate).
  • Observe every outgoing HTTP request and flag non-2xx responses.
  • Detect rage clicks (N rapid taps on the same target).
  • Pop the friction widget at the bottom of the screen with a contextual opener.
  • Stream the assembled Context Bundle to the Friction backend.

What gets captured #

A Context Bundle (schema 1.0) contains:

Field Notes
trigger type (api_error / uncaught_exception / rage_click / manual) + score
route Current route and recent history
interactions Last 50 taps (rage clicks flagged inline)
network Last 50 HTTP calls (status, duration, redacted error body)
errors Last 20 uncaught exceptions with stack traces
userFeedback Optional transcript captured by the widget

Privacy #

PII is stripped on the device before any bundle leaves the app. Email addresses, JWT-shaped tokens, credit-card patterns, long hex strings and phone numbers are redacted from network bodies and error messages. Only an allow-list of HTTP headers (content-type, accept, x-request-id) is included — extend it via:

Friction.instance?.redactor.allowedHeaders.add('x-correlation-id');

Manual reporting #

For "report a problem" buttons:

ElevatedButton(
  onPressed: () => Friction.report(
    reason: 'manual',
    userTranscript: 'The checkout total looks wrong on iPad.',
  ),
  child: const Text('Report'),
)

Configuration #

await Friction.init(
  appId: 'pk_live_…',
  baseUrl: 'https://your-backend.example.com', // your Friction backend
  captureHttp: true,
  captureExceptions: true,
  captureTaps: true,
);

Where tickets go #

Once a bundle is received, the backend synthesizes a structured ticket (title, summary, reproduction steps, suggested cause), embeds it for clustering, and — if you've linked a GitHub repo to the project — opens it as a real Issue with the auto-filed label.

Author #

Omar Mudhaffar — GitHub · LinkedIn

License #

MIT

0
likes
140
points
118
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Zero-config friction capture, voice-AI feedback, and auto-ticketing for Flutter apps. The AI knows what broke because it watched it break.

Repository (GitHub)
View/report issues

Topics

#error-reporting #observability #telemetry #feedback #voice

License

MIT (license)

Dependencies

audioplayers, flutter, http, http_parser, path_provider, permission_handler, record

More

Packages that depend on friction_sdk