Skip to content

Setting Up the App Debugger

Pro

What you'll learn

  • Generating the App Debugger overlay with the Impl + Noop pattern
  • Wiring the overlay into MaterialApp.router
  • Using build_prepare to strip the debugger from release builds
  • Exploring the built-in painter flags and debug pages
  • Extending the overlay with sub-bricks

Prerequisites

Step 1: Generate the App Debugger

bash
archipelago generate app_debugger

There are no generation variables — the brick produces the same structure for every project.

Step 2: Understand the Generated Structure

App Debugger uses the Impl + Noop pattern. Unlike infrastructure SDKs (monitoring, analytics), the debugger is a standalone debug/noop pair without a shared _api package — it is never consumed by other feature packages, only by the shell app.

features/app_debugger/
├── app_debugger/          # Real implementation — debug overlay, painter flags, built-in pages
└── app_debugger_noop/     # No-op — all methods are empty, zero overhead in release

The shell app imports one of these two packages. build_prepare controls which one is resolved at compile time.

Step 3: Configure build_prepare

yaml
# build_prepare.yaml
build_prepare:
  mappings:
    - debug: app_debugger
      release: app_debugger_noop

Run before building:

bash
# Development build — real overlay
dart run monorepo_toolkit build-prepare debug

# Release build — noop, zero overhead
dart run monorepo_toolkit build-prepare release

No runtime if (kDebugMode) checks needed. The noop variant compiles to nothing.

Step 4: Wire the Overlay into MaterialApp

The debugger overlay must wrap the entire widget tree. Pass it through MaterialApp.router's builder parameter:

dart
import 'package:app_debugger/app_debugger.dart'; // or app_debugger_noop

void main() async {
  await bootstrap();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    final debuggerSdk = GetIt.instance<AppDebuggerSDK>();

    return MaterialApp.router(
      routerConfig: appRouter.config(),
      builder: (context, child) =>
          debuggerSdk.overlay(child: child ?? const SizedBox.shrink()),
    );
  }
}

In debug builds, a floating action button appears on screen. Tap it to open the debug panel. In release builds, debuggerSdk.overlay is the noop passthrough — child is returned unchanged.

Step 5: Register the Feature

In your shell app's bootstrap.dart:

dart
import 'package:app_debugger/app_debugger.dart';

FeatureRegistry.register(AppDebuggerImpl());

Step 6: Explore the Painter Flags

The debug panel ships with 10 Flutter rendering flags you can toggle at runtime without rebuilding:

FlagWhat it shows
repaintRainbowFlashes widgets with random colours on each repaint
paintBaselinesDraws text baseline guides
paintLayerBordersOutlines compositing layer boundaries
paintPointersDraws touch pointer positions
paintSizeOutlines every widget's layout box
repaintTextRainbowHighlights text repaints specifically
disableClipLayersRemoves clip layers (exposes overflow)
disablePhysicalShapeLayersRemoves shadow/elevation layers
disableOpacityLayersRemoves opacity layers (finds unnecessary transparency)
profileBuildsLogs build counts and durations to the console

These map directly to Flutter's debugPaint* and RenderingFlutterBinding flags. Enabling repaintRainbow is the fastest way to spot widgets rebuilding more often than they should.

Step 7: Built-in Debug Pages

The overlay includes three pages out of the box, accessible from the debug panel navigation:

  • Painter Flags — Toggle all 10 flags described above
  • Device Info — OS version, screen dimensions, pixel ratio, locale
  • Package Info — App name, package name, version, build number

Step 8: Add Sub-Bricks for More Panels

The App Debugger is designed to be extended. Each sub-brick adds a new panel to the overlay:

Sub-brickPanel added
app_debugger_networkHTTP request/response log (requires Network SDK)
app_debugger_websocketWebSocket frame inspector
app_debugger_analyticsAnalytics event stream viewer
app_debugger_feature_flagLive feature flag overrides
app_debugger_storageSharedPreferences and secure storage browser

Generate them individually after the base debugger is set up:

bash
archipelago generate app_debugger_network
archipelago generate app_debugger_storage

Each sub-brick registers its own panel automatically via the feature registry — no manual wiring required.

Next Steps

Built by Banua Coder