vibebug_flutter 0.4.1
vibebug_flutter: ^0.4.1 copied to clipboard
Crash reporting and visual bug capture for Flutter apps — reports issues to Vibe Bug Tracker with screenshots, widget selectors, and an offline queue.
vibebug_flutter #
Crash reporting plus Chrome-extension-style visual bug capture for Flutter apps — sends issues to Vibe Bug Tracker with screenshots, widget selectors, and Flutter-specific AI markdown.
Testers in your app can capture a widget, crop and highlight the region, add screenshots, and send a fully-described issue straight to your tracker board — no Chrome extension required.
Features #
- Zero-config setup — one command wires everything into your app, no manual code required
- Built-in sign-in + project picker — first launch shows a login screen, then a project dropdown; from then on issues are tracked against that project automatically
- Automatic crash reporting — uncaught exceptions,
FlutterError.onError, and platform errors are reported with stack traces - Offline queue — reports are queued and retried when connectivity returns, with de-duplication
- Draggable Report button — testers can move the bubble anywhere on screen
- Widget picker + capture region editor — tap a widget to capture it, then crop/adjust the region and draw highlight marks
- Multi-screenshot issues — up to 8 captures per issue, like the Chrome extension
- Flutter-specific AI markdown — issue descriptions include widget selectors, route, and Flutter fix guidance
- Caught-exception API — report handled errors from anywhere in your code
Requirements #
- Flutter
>=3.16.0 - Dart SDK
>=3.2.0 <4.0.0 - A Vibe Bug Tracker account, and a tester / owner / admin account with access to a project
Installation #
flutter pub add vibebug_flutter
Then run the setup wizard:
dart run vibebug_flutter:configure
The configure command:
- Rewrites
main.dartsorunApp()runs insideVibeBug.runGuarded(), withVibeBug.initialize()awaited just before it. - Finds your
MaterialApp/MaterialApp.routerand wiresVibeBugScopeinto itsbuilder:. - Generates
lib/vibebug_config.dartwith your backend base URL (no credentials — sign-in happens at runtime).
It always shows a diff and asks for confirmation before writing anything. Useful flags:
| Flag | Purpose |
|---|---|
--yes |
Skip the confirmation prompt |
--base-url <url> |
Point at a self-hosted backend instead of the default https://vibebugtracker.com |
It takes a .bak backup of every file it touches. If your main.dart/MaterialApp don't match one of the simple shapes it knows how to rewrite safely, it leaves a // TODO(vibebug): ... comment explaining what to do manually — see Troubleshooting.
That's it — run your app. First launch shows a sign-in screen (tester/owner/admin email + password), then a project picker. Once a project is selected, every report from that device tracks against it until the user signs out (VibeBug.signOut()).
Example app #
A complete runnable demo app lives in example/ — clone the repo and run it to test every SDK feature against your own Vibe Bug Tracker account:
git clone https://github.com/adnanpk44/vbt.git
cd vbt/example
flutter pub get
flutter run
It exercises crash reporting, caught exceptions, the draggable capture bubble, widget picker, and the offline queue.
How it works #
┌──────────────────────────────────────────────────────────────┐
│ Your app (main.dart) │
│ VibeBug.runGuarded(() { ensureInitialized(); runApp(); }) │
│ │ catches uncaught errors │
│ ▼ │
│ VibeBugScope (wraps MaterialApp.builder) │
│ │ • floating Report bubble (draggable) │
│ │ • sign-in gate + project picker on first launch │
│ │ • widget hit-testing for selectors │
│ ▼ │
│ VibeBug.initialize(VibeBugOptions(...)) │
│ │ • authenticates (token / email+password) │
│ │ • offline queue (SharedPreferences) │
│ │ • de-duplication window │
│ ▼ │
│ Vibe Bug Tracker API (/api/extension/issues) │
└──────────────────────────────────────────────────────────────┘
Every report (crash, caught exception, or visual capture) goes through the same pipeline: authenticate → resolve target project/board/developer → enqueue → send immediately (or queue for offline retry).
Manual / advanced setup #
Skip configure and wire things up yourself if you want full control, or if you're integrating into a headless/CI/kiosk build. Supplying email/password/token to VibeBugOptions (or setting enableAuthGate: false) bypasses the built-in sign-in/picker screens entirely — this is the path used by this repo's own flutter-vibebug-demo app.
dependencies:
vibebug_flutter:
path: ../packages/vibebug_flutter
Initialize and wrap with the same zone + MaterialApp builder:
import 'package:flutter/material.dart';
import 'package:vibebug_flutter/vibebug_flutter.dart';
void main() {
// ensureInitialized and runApp must run in the same zone.
VibeBug.runGuarded(() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
});
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
static final _navKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: _navKey,
// Keep VibeBugScope under MaterialApp so Directionality/Theme exist.
builder: (context, child) => VibeBugScope(
navigatorKey: _navKey,
child: child ?? const SizedBox.shrink(),
),
home: const HomePage(),
);
}
}
await VibeBug.initialize(VibeBugOptions(
onIssueSent: (issueId) => debugPrint('Reported $issueId'),
));
Call initialize before or after runApp (e.g. from your root widget after setup). If you want the built-in sign-in/picker gate (rather than supplying email/password/token yourself) and are wiring things up by hand instead of via configure, await initialize() before runApp() — otherwise your app's first frame can flash before the gate takes over. The generated configure output always does this for you.
Visual bug reporting #
Put VibeBugScope in MaterialApp.builder (not above MaterialApp). When using MaterialApp.router, pass the router navigator key:
MaterialApp.router(
routerConfig: goRouter,
builder: (context, child) => VibeBugScope(
navigatorKey: goRouter.routerDelegate.navigatorKey,
child: child ?? const SizedBox.shrink(),
),
)
- Drag the bubble to reposition it (position is remembered)
- Tap the bubble → tap a widget to capture it
- Crop / highlight in the full-screen editor, add a per-capture note, then Save
- Navigate to other screens freely, tap Report again to add more (up to 8)
- Tap the badge on the bubble, then sign in with the tester account if needed
- Select the project, board, developer, and priority for this issue, then Send
Long-press the bubble to clear draft captures.
Options #
VibeBugOptions fields:
| Field | Default | Purpose |
|---|---|---|
baseUrl |
https://vibebugtracker.com |
Backend base URL (self-hosting) |
token |
null |
API token (bypasses sign-in) |
email / password |
null |
Direct credentials (bypasses sign-in) |
projectId / boardId / assignedTo |
null |
Default target project/board/developer |
autoReportCrashes |
true |
Report uncaught exceptions automatically |
reportInBackground |
true |
Send immediately; false = queue only |
defaultPriority |
high |
Priority for auto-reported crashes |
dedupeWindow |
5 min |
Suppress duplicate reports within this window |
screenshotProvider |
null |
Future<String?> Function() for extra screenshots |
onIssueSent |
null |
Callback with the created issue id |
onError |
null |
Callback for send/queue errors |
enableAuthGate |
null |
Auto-detect: on when no creds supplied, off otherwise |
autoSelectSoleProject |
false |
Skip picker when sign-in resolves to exactly one project |
API #
VibeBug (static) #
| Method | Purpose |
|---|---|
initialize(options) |
Configure the SDK before runApp |
runGuarded(runner) |
Wrap runApp to catch async zone errors |
signIn(email:, password:) |
Authenticate a tester/owner/admin account |
signOut() |
Clear session + project selection |
selectProject(id) / selectBoard(id) / selectDeveloper(id) |
Change the active target |
reportException(error, stack, ...) |
Report a caught exception |
reportIssue(description:, ...) |
Report a text issue (optional screenshot) |
reportIssueWithCaptures(summary:, captures:, ...) |
Report a multi-screenshot visual issue |
flushPendingReports() |
Retry queued reports |
Widgets #
| Widget | Purpose |
|---|---|
VibeBugScope |
Draggable capture bubble + gate; wrap MaterialApp.builder |
VibeBugReportButton |
Legacy text-only report button |
VibeBugErrorBoundary |
Report subtree framework errors with a custom fallback |
Models #
VibeBugScreenshotShot— one visual capture (selected + full screenshots, selector, semantics)VibeBugProject/VibeBugBoard/VibeBugDeveloper— target selection metadata
Caught exceptions #
try {
await riskyOperation();
} catch (e, stack) {
await VibeBug.reportException(e, stack, description: 'Checkout failed');
}
Programmatic multi-capture submit #
await VibeBug.reportIssueWithCaptures(
summary: 'Checkout CTA overlaps total on small screens',
captures: shots, // List<VibeBugScreenshotShot>
);
Troubleshooting configure #
configure refuses to guess when your main.dart or MaterialApp don't match a shape it can rewrite safely. Each reason it can print, and the manual fix:
| Reason | Manual fix |
|---|---|
Multiple/zero main() or runApp() |
Wrap your existing runApp(...) call in VibeBug.runGuarded(() async { ...; await VibeBug.initialize(VibeBugOptions(baseUrl: ...)); runApp(...); }); yourself. |
runApp() nested inside another callback, or has trailing code (e.g. .then(...)) |
Same as above — move the VibeBug.initialize() call to just before wherever runApp() actually runs. |
VibeBug.runGuarded() present but no VibeBug.initialize() inside it |
Add await VibeBug.initialize(VibeBugOptions(baseUrl: ...)); inside the runGuarded closure, before runApp(). |
Multiple/zero MaterialApp(...) usages, or an existing non-trivial builder: |
Wrap your MaterialApp's builder: yourself, per the Manual / advanced setup example above. |
Notes #
- Widget inspection works best in debug/profile builds where Flutter exposes widget creators
- Screenshot capture requires
VibeBugScope(uses an internalRepaintBoundary) - Requires a tester, project admin, or workspace owner/admin account with access to the target project — the SDK always reports as a tester (
X-VIT-Acting-Role: tester), so owner/admin accounts with no dedicated tester seat are included automatically - Reports use the same
/api/extension/issuesendpoint with ascreenshots[]payload as the Chrome extension
Development #
cd packages/vibebug_flutter
flutter pub get
flutter analyze
flutter test
License #
MIT — see LICENSE. Part of the Vibe Bug Tracker ecosystem.