friction_sdk 0.0.4
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 (
Nrapid 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