A powerful WebView inspector and debugging tool for flutter_inappwebview. Provides real-time console monitoring, JavaScript execution, and script history management with a draggable overlay interface.
π€ Developed with Claude: This Flutter library was developed using Vibe coding methodology in collaboration with Claude AI, showcasing the power of AI-assisted development and human-AI collaborative programming.
- English | νκ΅μ΄ (Korean) | ζ₯ζ¬θͺ (Japanese)
- No Manual Widget Placement: Inspector UI automatically injects as overlay when
show()is called - Smart Context Discovery: Automatic BuildContext discovery via WidgetsBinding and NavigatorKey fallback
- Developer-Controlled: User controls when auto-injection is enabled via debug mode initialization
- Hot Reload Compatible: Robust overlay system that works seamlessly with Flutter's hot reload
- Performance Optimized: Optional NavigatorKey integration for instant context access
- Zero Configuration: Just call
toggle()and the UI appears - no Stack widgets or manual placement needed
- Live Console Output: Monitor all JavaScript console messages (
log,warn,error,debug) in real-time - Color-coded Messages: Different colors for different log levels for easy identification
- Timestamp Display: Each message includes precise timestamp information
- Multi-line Support: Full support for long messages and multi-line output
- Clean Interface: Removed unnecessary labels for streamlined debugging experience
- Interactive Console: Execute JavaScript code directly in your WebView with intelligent result handling
- Smart DOM Object Processing:
document.querySelector("h1")β Shows element details (tag, id, class, text content)document.querySelectorAll("p")β Lists all matching elements with comprehensive informationdocument.body.classListβ Automatically converts to readable array format- Functions and complex objects β Displays in developer-friendly format
- Enhanced Error Handling: Comprehensive error messages with helpful suggestions for common DOM operations
- Unicode & Base64 Support: Advanced script encoding options for complex scenarios
- Pre-loaded Scripts: 15+ commonly used JavaScript snippets ready to use immediately
- Frequency-based Sorting: Most-used scripts automatically appear first
- Memory-based Storage: Fast, lightweight history management without file I/O
- Smart Suggestions: Context-aware script recommendations
- Usage Tracking: Automatically tracks and prioritizes frequently used scripts
- Multiple WebView Support: Handle unlimited WebViews in a single application
- Easy Switching: Quick dropdown to switch between registered WebViews
- Individual Monitoring: Each WebView maintains its own console and execution context
- Automatic Registration: Simple API to register and manage WebView instances
- 8 Languages Supported: English, Korean, Japanese, Spanish, French, German, Chinese (Simplified), Portuguese
- Auto-detection: Automatic language detection from system locale
- Easy Localization: Simple API to set preferred language
- Consistent UI: All interface elements properly localized
- Draggable Overlay: Move the inspector anywhere on screen with smooth drag interactions
- Resizable Interface: Switch between compact and maximized modes for different use cases
- SafeArea Aware: Automatically adjusts to device screen constraints and notches
- Stack-based Architecture: Stable popup system without overlay conflicts
- Clean Design: Minimal, developer-focused interface optimized for productivity
Add this to your package's pubspec.yaml file:
dependencies:
inappwebview_inspector: ^0.2.1
flutter_inappwebview: ^6.1.5Then run:
$ flutter pub getAdd this to your main() function:
import 'package:flutter/foundation.dart';
import 'package:inappwebview_inspector/inappwebview_inspector.dart';
void main() {
// Zero setup initialization - show() will auto-inject UI
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxScriptHistoryCount: 25,
localizations: InAppWebViewInspectorLocalizations.english, // Change as needed
onScriptExecuted: (script, webViewId) {
print('Executed: $script on $webViewId');
},
onConsoleLog: (log) {
print('Console [${log.levelText}]: ${log.message}');
},
);
}
runApp(MyApp());
}class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WebView Inspector Demo',
// Add navigatorKey for optimal auto UI injection performance
navigatorKey: InAppWebViewInspector.navigatorKey,
home: MyWebViewPage(),
);
}
}β¨ New: Zero Setup Auto UI Injection - No need to manually add widgets to your UI!
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:inappwebview_inspector/inappwebview_inspector.dart';
class MyWebViewPage extends StatefulWidget {
@override
_MyWebViewPageState createState() => _MyWebViewPageState();
}
class _MyWebViewPageState extends State<MyWebViewPage> {
InAppWebViewController? webViewController;
final String webViewId = 'main_webview';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WebView with Inspector'),
actions: [
// Toggle button - UI will auto-inject when pressed!
IconButton(
icon: Icon(Icons.bug_report),
onPressed: InAppWebViewInspector.toggle,
tooltip: 'Toggle Inspector\n(Zero Setup - UI Auto-Injected!)',
),
],
),
// β¨ No Stack needed! Inspector UI auto-injects as overlay
body: Column(
children: [
// Your main WebView - Inspector UI auto-injects when show() is called
Expanded(
child: InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri('https://flutter.dev'),
),
onWebViewCreated: (controller) {
webViewController = controller;
// Register WebView with inspector
InAppWebViewInspector.registerWebView(
webViewId,
controller,
'https://flutter.dev',
);
},
onLoadStop: (controller, url) {
// Update URL in inspector when navigation occurs
if (url != null) {
InAppWebViewInspector.updateWebViewUrl(
webViewId,
url.toString(),
);
}
},
onConsoleMessage: (controller, consoleMessage) {
// Forward console messages to inspector
InAppWebViewInspector.addConsoleLog(
webViewId,
consoleMessage,
);
},
initialSettings: InAppWebViewSettings(
isInspectable: true, // Enable debugging
javaScriptEnabled: true,
domStorageEnabled: true,
),
),
),
],
),
);
}
@override
void dispose() {
// Clean up when page is disposed
InAppWebViewInspector.unregisterWebView(webViewId);
super.dispose();
}
}// Show/hide inspector - UI automatically injects as overlay!
InAppWebViewInspector.show(); // β¨ Auto-injects UI overlay
InAppWebViewInspector.hide(); // Removes overlay
InAppWebViewInspector.toggle(); // β¨ Toggle with auto-injection
// Enable/disable inspector
InAppWebViewInspector.enable();
InAppWebViewInspector.disable();
// Check status
bool isVisible = InAppWebViewInspector.isVisible;
bool isEnabled = InAppWebViewInspector.isEnabled;// Zero setup - show() always auto-injects UI
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxScriptHistoryCount: 25,
maxConsoleLogCount: 500,
localizations: InAppWebViewInspectorLocalizations.english,
onScriptExecuted: (script, webViewId) {
print('Script executed on $webViewId: $script');
},
onConsoleLog: (log) {
print('Console [${log.levelText}]: ${log.message}');
},
);
}// Only initialize in production if needed
if (!kReleaseMode) {
InAppWebViewInspector.initializeProduction(
maxConsoleLogCount: 50,
enableAutoResultLogging: false,
enableScriptHistory: false,
localizations: InAppWebViewInspectorLocalizations.english,
);
}// Advanced configuration with auto UI injection
if (kDebugMode) {
InAppWebViewInspector.initializeWithConfig(
InAppWebViewInspectorConfig(
debugMode: true,
maxConsoleLogCount: 1000,
enableAutoResultLogging: true,
enableUnicodeQuoteNormalization: true,
enableBase64ScriptEncoding: true,
enableScriptHistory: true,
maxScriptHistoryCount: 30,
localizations: InAppWebViewInspectorLocalizations.korean, // Multi-language support
onScriptExecuted: (script, webViewId) {
// Custom script execution callback
analytics.logEvent('script_executed', {'webview_id': webViewId});
},
onConsoleLog: (log) {
// Custom console logging
if (log.level == ConsoleMessageLevel.ERROR) {
crashlytics.recordError(log.message, null);
}
},
onError: (error, webViewId) {
// Error handling callback
print('Inspector error in $webViewId: $error');
},
),
);
}// Available localizations
InAppWebViewInspectorLocalizations.english
InAppWebViewInspectorLocalizations.korean
InAppWebViewInspectorLocalizations.japanese
InAppWebViewInspectorLocalizations.spanish
InAppWebViewInspectorLocalizations.french
InAppWebViewInspectorLocalizations.german
InAppWebViewInspectorLocalizations.chineseSimplified
InAppWebViewInspectorLocalizations.portuguese
// Auto-detect from system locale
final localization = InAppWebViewInspectorLocalizations.getByLanguageCode(
Localizations.localeOf(context).languageCode
);class MultiWebViewExample extends StatefulWidget {
@override
_MultiWebViewExampleState createState() => _MultiWebViewExampleState();
}
class _MultiWebViewExampleState extends State<MultiWebViewExample> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Multiple WebViews'),
actions: [
// Single toggle button for all WebViews - UI auto-injects!
IconButton(
icon: Icon(Icons.bug_report),
onPressed: InAppWebViewInspector.toggle,
tooltip: 'Toggle Inspector\n(Zero Setup Auto UI)',
),
],
),
// β¨ No Stack needed! Inspector UI auto-injects as overlay
body: Column(
children: [
// First WebView
Expanded(
child: InAppWebView(
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView(
'webview_1',
controller,
'https://flutter.dev',
);
},
onConsoleMessage: (controller, consoleMessage) {
InAppWebViewInspector.addConsoleLog('webview_1', consoleMessage);
},
initialSettings: InAppWebViewSettings(
isInspectable: true,
javaScriptEnabled: true,
),
),
),
// Second WebView
Expanded(
child: InAppWebView(
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView(
'webview_2',
controller,
'https://dart.dev',
);
},
onConsoleMessage: (controller, consoleMessage) {
InAppWebViewInspector.addConsoleLog('webview_2', consoleMessage);
},
initialSettings: InAppWebViewSettings(
isInspectable: true,
javaScriptEnabled: true,
),
),
),
],
),
);
}
}// Add custom messages from Flutter
InAppWebViewInspector.instance.addCustomConsoleLog(
InAppWebViewInspectorConsoleMessage(
webViewId: 'main',
level: ConsoleMessageLevel.WARNING,
message: 'Custom warning from Flutter side',
source: null, // Clean interface without source labels
line: null,
timestamp: DateTime.now(),
),
);
// Add development debug messages
InAppWebViewInspector.instance.addCustomConsoleLog(
InAppWebViewInspectorConsoleMessage(
webViewId: 'main',
level: ConsoleMessageLevel.LOG,
message: 'Flutter lifecycle: App resumed',
source: null,
line: null,
timestamp: DateTime.now(),
),
);// Execute custom scripts programmatically
void executeCustomScripts() {
final inspector = InAppWebViewInspector.instance;
// Simple value retrieval
inspector.executeScript('document.title');
// Complex DOM operations
inspector.executeScript('''
const links = document.querySelectorAll('a');
Array.from(links).map(link => ({
text: link.textContent?.trim(),
href: link.href,
className: link.className
}));
''');
// Error handling example
inspector.executeScript('''
try {
const result = performComplexOperation();
console.log('Operation successful:', result);
return result;
} catch (error) {
console.error('Operation failed:', error.message);
return { error: error.message, stack: error.stack };
}
''');
}The inspector comes with 15+ ready-to-use JavaScript snippets:
document.title- Get current page titlewindow.location.href- Get current URLdocument.readyState- Check page load statedocument.getElementsByTagName("*").length- Count all elements
document.querySelector("selector")- Find single element with detailsdocument.querySelectorAll("selector")- Find all matching elementsdocument.body.innerHTML- Get page HTML contentdocument.cookie- View all cookies
navigator.userAgent- Get browser informationwindow.innerWidth + "x" + window.innerHeight- Get viewport sizeperformance.now()- High-precision timingObject.keys(window)- List global variables
localStorage.getItem("key")- Access local storagesessionStorage.getItem("key")- Access session storage
console.log("Hello World");- Basic console logging
The inspector running on iOS showing the draggable overlay interface
The inspector running on Android with the same powerful debugging features
- π±οΈ Draggable Overlay: Move the inspector anywhere on screen
- π± Responsive Design: Adapts to different screen sizes and orientations
- π― WebView Selector: Dropdown to switch between multiple WebViews
- β¨οΈ Interactive Console: JavaScript input field with history dropdown
- π Real-time Logs: Color-coded console output with timestamps
- π Resizable Interface: Toggle between compact and maximized modes
Major Feature: Zero Setup Auto UI Injection
- No more manual widget placement required
- Automatic context discovery and overlay injection
- Simplified integration with just
toggle()calls
Before (v0.1.x): Manual Stack placement required
// β Old way - Still works but not needed
Scaffold(
body: Stack(
children: [
YourContent(),
const InAppWebViewInspectorWidget(), // Manual placement
],
),
)After (v0.2.0): Zero setup auto-injection (Recommended)
// β
New way - UI auto-injects as overlay
Scaffold(
body: YourContent(), // No Stack needed!
)
// Just call toggle - UI appears automatically
InAppWebViewInspector.toggle();For optimal performance, add NavigatorKey to your MaterialApp:
// β
Recommended for v0.2.0
MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // New
home: YourHomePage(),
)dependencies:
inappwebview_inspector: ^0.2.1 # Updated
flutter_inappwebview: ^6.1.5MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // Add this line
home: YourHomePage(),
)You can now remove manual Stack placement:
// Before: Required Stack
Scaffold(
body: Stack(
children: [
YourContent(),
const InAppWebViewInspectorWidget(),
],
),
)
// After: Simple layout - Inspector auto-injects
Scaffold(
body: YourContent(),
)// Inspector UI will auto-inject when you call:
InAppWebViewInspector.show();
InAppWebViewInspector.toggle();- Faster Context Discovery: NavigatorKey provides instant context access
- Reduced Widget Tree: No manual Stack widgets needed
- Hot Reload Friendly: Robust overlay system works seamlessly with Flutter's hot reload
- Inspector not appearing: Add
navigatorKey: InAppWebViewInspector.navigatorKeyto MaterialApp - "No Overlay widget found": Ensure you're calling
toggle()after initialization - Layout issues: Remove manual Stack placement - auto-injection handles positioning
- Automatic UI Injection: Zero setup overlay system
- Smart Context Discovery: Automatic BuildContext discovery
- NavigatorKey Integration: Optional performance optimization
- Enhanced Error Recovery: Better fallback mechanisms
- Hot Reload Compatibility: Improved development experience
New Simplified Approach: No manual widget placement required!
β New Zero Setup Method: Auto UI injection (Recommended)
// 1. Add NavigatorKey for optimal performance
MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // β
Optimal setup
home: MyWebViewPage(),
)
// 2. Simple UI with no Stack needed
Scaffold(
body: Column( // β
Simple layout
children: [
Expanded(
child: InAppWebView(
// Register WebView and inspector auto-injects UI
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView('main', controller, url);
},
),
),
],
),
)
// 3. Toggle inspector - UI auto-appears as overlay!
InAppWebViewInspector.toggle(); // β
Zero manual UI workFor advanced use cases, you can still manually place the widget:
Scaffold(
body: Stack(
children: [
YourMainContent(),
const InAppWebViewInspectorWidget(), // Manual placement
],
),
)- Inspector not appearing: Ensure NavigatorKey is added to MaterialApp for optimal context discovery
- Auto UI injection fails: Check that you're in debug mode and inspector is properly initialized
- "No Overlay widget found": Add
navigatorKey: InAppWebViewInspector.navigatorKeyto your MaterialApp - Dependency conflict with git-sourced flutter_inappwebview: Add dependency override
If your app uses flutter_inappwebview from git source:
dependencies:
inappwebview_inspector: ^0.2.1
flutter_inappwebview:
git:
url: https://github.com/pichillilorenzo/flutter_inappwebview.git
ref: master
path: flutter_inappwebview
dependency_overrides:
flutter_inappwebview:
git:
url: https://github.com/pichillilorenzo/flutter_inappwebview.git
ref: master
path: flutter_inappwebviewDevelopment Build with Auto UI Injection:
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxConsoleLogCount: 500,
);
}Production Build (Optional):
if (!kReleaseMode) {
InAppWebViewInspector.initializeProduction(
maxConsoleLogCount: 50,
enableScriptHistory: false,
);
}The example app demonstrates:
- β Complete WebView integration with inspector
- β Multi-language support demonstration
- β Pre-loaded script usage
- β Enhanced DOM object handling
- β Multiple WebView management
- β Custom script execution examples
Run the example:
cd example && flutter run- Flutter: >= 3.24.0
- Dart: >= 3.5.0
- flutter_inappwebview: >= 6.1.5
| Platform | Status | Notes |
|---|---|---|
| Android | β Full Support | All features available |
| iOS | β Full Support | All features available |
This project demonstrates the power of AI-assisted development using Claude and Vibe coding methodology. Contributions are welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Test your changes thoroughly
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone the repository
git clone https://github.com/baccusf/inappwebview_inspector.git
cd inappwebview_inspector
# Install dependencies
flutter pub get
# Run tests
flutter test
# Run example
cd example && flutter runThis project is licensed under the MIT License - see the LICENSE file for details.
- π€ Claude AI: This library was developed through AI-human collaborative programming using Claude
- β‘ Vibe Coding: Demonstrated the effectiveness of AI-assisted development methodology
- π Flutter Community: For providing the amazing Flutter framework
- π flutter_inappwebview: For the excellent WebView foundation
- π Issues: Report bugs and issues
- π‘ Features: Request new features
- π Documentation: Check the comprehensive CLAUDE.md for development guidance
- π¬ Discussions: Join community discussions
- π¦ pub.dev: Package on pub.dev
- π Repository: GitHub Repository
- π flutter_inappwebview: Core WebView package
- π€ Claude: Learn more about Claude AI
Happy debugging with AI-assisted development! πβ¨π€

