Images not loading? Loading slow? Stale avatars that never update? Memory ballooning? Image HTTP traffic in Flutter is fetched by dart:io image loaders and never surfaces the layout size or cache origin a network inspector needs — this tool is the visibility layer.
Every image loaded through BuoyImage appears in a live registry with where it came from (memory cache / disk cache / network), how long it took, how big it decoded versus how big it displayed, and exactly why it failed.
The React Native build of this tool, running here on mock data. The Flutter port ships the same panels — walk the tour, or skip it and start tapping.
Not a video — this is the shipped tool on mock loads. Image HTTP never touches the JS network stack, so network devtools are permanently blind to it.
flutter pub add buoy_imagesFlutter has no app-wide Image decorator hook, so capture is opt-in at the widget level — use BuoyImage in place of Image / CachedNetworkImage:
import 'package:buoy_images/buoy_images.dart';
BuoyImage(
provider: CachedNetworkImageProvider(url), // or NetworkImage(url), AssetImage(...)
width: 120,
height: 120,
)
import 'package:buoy_images/buoy_images.dart';
BuoyImage(
provider: CachedNetworkImageProvider(url), // or NetworkImage(url), AssetImage(...)
width: 120,
height: 120,
)
It wraps your ImageProvider, measures the rendered box for the oversize audit, and owns the props so reload/retry and simulations work.
Flutter has no app-wide Image decorator hook like React Native. Capture is opt-in: wrap each load in BuoyImage, which instruments your ImageProvider, watches layout size for the oversize audit, and owns reload / retry / simulation props.
Buoy's own UI is excluded from capture — the tool never appears in its own registry.
BuoyImage appear in the registry — plain Image.network / CachedNetworkImage without the wrapper stay invisible.width × height × 4 bytes) — the same math platforms use for RGBA bitmaps.The same live registry streams to Buoy Desktop — the full tool (list, detail, simulations, mass actions) on a big screen. And with the MCP server, an agent can list every load with get_images, reload or retry with image_action, and flip failure simulations with set_image_simulation.
Image HTTP traffic in Flutter is fetched by dart:io image loaders and never surfaces the layout size or cache origin an inspector needs. Buoy's registry records each load's cache verdict (memory, disk, or network), its timing, decoded size versus displayed size, and the exact reason it failed.
Flutter has no app-wide Image decorator hook, so capture is opt-in per widget: use BuoyImage(provider: ...) in place of Image or CachedNetworkImage. It wraps your ImageProvider and measures the rendered box for the oversize audit.
Decoded pixels are compared against the laid-out size × device pixel ratio, Lighthouse-style, with the estimated wasted decoded bytes and the dimensions you should serve instead. Tiny sources stretched into a large box are flagged the other way, as upscaled.