riverpod_timeline 1.1.0 copy "riverpod_timeline: ^1.1.0" to clipboard
riverpod_timeline: ^1.1.0 copied to clipboard

A Riverpod debugging and state-inspection package that records every provider update, tracks dependencies, visualizes state changes, and supports time-travel debugging.

riverpod_timeline #

Debug and inspect Riverpod state with zero app logic changes. Records every provider update, tracks dependencies, visualizes state changes, and supports time-travel debugging.

Features: Observer | Timeline Viewer | Dependency Graph | Performance Dashboard | Time Travel | Export/Import | Floating Overlay
Safety:    Auto-disabled in release builds (opt-in available)

Screenshots #

Timeline Viewer Dependency Graph
[Timeline] [Graph]
Performance Dashboard Time Travel Debugging
[Performance] [Time Travel]
Export / Import
[Export]

Requirements #

  • Flutter >=3.22.0
  • Riverpod ^3.0.0
  • Dart ^3.12.1

Works with all Riverpod provider types: Provider, NotifierProvider, AsyncNotifierProvider, FutureProvider, StreamProvider, StreamNotifierProvider.


Install #

dependencies:
  flutter_riverpod: ^3.0.0
  riverpod_timeline: ^1.0.0

Quick Start #

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_timeline/riverpod_timeline.dart';

final _navigatorKey = GlobalKey<NavigatorState>();

void main() {
  // 1. Initialize (before runApp)
  RiverpodTimeline.initialize();

  runApp(
    // 2. RiverpodTimelineScope wraps ProviderScope (adds observer + overlay)
    RiverpodTimelineScope(
      navigatorKey: _navigatorKey,
      child: MaterialApp(
        navigatorKey: _navigatorKey,
        home: const MyApp(),
      ),
    ),
  );
}

That's it. A floating debug button appears on screen. Tap it to open the full debug panel (Timeline, Graph, Metrics).


Configuration #

RiverpodTimeline.initialize(
  /// Max events kept in memory. Oldest are pruned when exceeded.
  maxEvents: 10000,

  /// Track rebuild counts, update frequency, and durations.
  enablePerformanceTracking: true,

  /// Record parent/child provider dependency relationships.
  enableDependencyTracking: true,

  /// Force-enable in release builds (default: off — auto-disabled).
  enableReleaseMode: false,

  /// Capture stack traces with each event (expensive; debugging only).
  captureStackTraces: false,

  /// Print events to the debug console via [debugPrint].
  enableLogging: false,

  /// Show the floating debug overlay automatically (default: true).
  /// You can always show/hide it manually regardless of this setting.
  enableOverlay: true,
);

Override overlay at runtime #

// Show/hide the floating button (no need to reinitialize)
RiverpodTimelineOverlay.setVisible(false);
RiverpodTimelineOverlay.setVisible(true);
RiverpodTimelineOverlay.toggleVisibility();

// Remove the overlay entirely
RiverpodTimelineOverlay.disable();

// Re-add it
RiverpodTimelineOverlay.enable(
  timelineController: tl.controller,
  graphController: tl.graphController,
  metricsCollector: tl.metricsCollector,
  context: context,
);

Manual setup (without RiverpodTimelineScope) #

If you prefer not to use RiverpodTimelineScope, wire things up yourself:

void main() {
  RiverpodTimeline.initialize(enableOverlay: false); // no auto-overlay

  runApp(
    ProviderScope(
      observers: [RiverpodTimeline.instance.observer],
      child: MaterialApp(
        navigatorKey: _navigatorKey,
        home: const MyApp(),
      ),
    ),
  );
}

// Access the panel programmatically:
final tl = RiverpodTimeline.instance;

Navigator.of(context).push(
  MaterialPageRoute(
    builder: (_) => ProviderTimelineView(controller: tl.controller),
  ),
);

// Or use individual widgets:
//   ProviderTimelineView(controller: tl.controller)
//   ProviderDependencyGraph(controller: tl.graphController)
//   RiverpodPerformanceDashboard(collector: tl.metricsCollector)

Time Travel Debugging #

final tl = RiverpodTimeline.instance;

tl.replay();            // Play all recorded events
tl.pause();             // Pause (maintains position)
tl.resumeReplay();      // Resume from current position
tl.stepForward();       // Next event
tl.stepBackward();      // Previous event

// Lower-level control:
final ttc = tl.timeTravelController;
ttc.goToEvent(5);       // Jump to index
ttc.goToStart();
ttc.goToEnd();
ttc.replaySpeedMs = 200; // ms between events (50-5000)
ttc.state;               // ReplayState.playing | .paused | .stopped

Export & Import #

final tl = RiverpodTimeline.instance;

// Export
final Map<String, dynamic> data = tl.exportJson();
final String json = tl.exportJsonString();

// Import
tl.importJson(data);
tl.importJsonString(json);

Includes: all events, provider metadata, dependency graph, performance metrics, and config.


Production Safety #

The timeline auto-disables in release builds (zero overhead, no code changes).

// Force-enable for internal/dogfooding builds:
RiverpodTimeline.initialize(
  enableReleaseMode: true,
);

When disabled:

  • No events recorded
  • No memory allocated
  • ProviderObserver methods are no-ops

Memory #

  • maxEvents (default 10,000) limits memory usage
  • Oldest events pruned automatically
  • All data is in-memory; no disk I/O during recording

Architecture #

lib/
├── riverpod_timeline.dart                      # Barrel export
└── src/
    ├── config.dart                             # RiverpodTimelineConfig
    ├── riverpod_timeline_api.dart              # RiverpodTimeline (singleton)
    ├── models/                                 # Data models
    │   ├── event_type.dart                     # created / updated / disposed / refreshed / error
    │   ├── timeline_event.dart                 # Single event with value snapshots
    │   ├── provider_info.dart                  # Provider metadata
    │   ├── dependency_node.dart                # Graph node + cycle detection
    │   └── performance_metrics.dart            # Per-provider stats
    ├── observer/timeline_observer.dart         # ProviderObserver
    ├── storage/timeline_storage.dart           # In-memory ring buffer
    ├── timeline/timeline_controller.dart       # Query & filter
    ├── graph/dependency_graph.dart             # Dependency graph controller
    ├── replay/time_travel_controller.dart      # Playback engine
    ├── metrics/metrics_collector.dart          # Performance data
    ├── widgets/                                # Flutter UI
    │   ├── timeline_viewer.dart                # ProviderTimelineView
    │   ├── dependency_graph_widget.dart        # ProviderDependencyGraph
    │   ├── performance_dashboard.dart          # RiverpodPerformanceDashboard
    │   └── event_detail_widget.dart            # Expandable event card
    ├── overlay/debug_overlay.dart              # Floating debug button
    └── export/timeline_exporter.dart           # JSON export/import

Data Flow #

ProviderContainer ──> TimelineObserver ──> TimelineStorage
                         │                       │
                    DependencyGraph        TimelineController
                    Controller                  │
                         │                   Widgets
                    MetricsCollector            │
                         │              TimeTravelController
                    PerformanceSummary     (replay engine)

API Reference #

Method Returns Description
RiverpodTimeline.initialize(...) RiverpodTimeline Init before runApp
RiverpodTimeline.instance RiverpodTimeline Singleton accessor
RiverpodTimeline.reset() void Clear singleton (tests)
tl.config RiverpodTimelineConfig Current config
tl.observer TimelineObserver Pass to ProviderScope
tl.controller TimelineController Query/filter events
tl.graphController DependencyGraphController Dependency inspection
tl.timeTravelController TimeTravelController Replay engine
tl.metricsCollector MetricsCollector Performance data
tl.isEnabled bool Whether engine is active

Example App #

cd example && flutter run

Showcases: multiple provider types, timeline viewer, dependency graph, performance dashboard, export, and the developer overlay.


Testing #

flutter test
flutter test --coverage

Covers: serialization, storage, dependency graph, time travel, metrics, export/import, and singleton lifecycle.


Contributing #

  1. Fork the repo
  2. Create a branch: git checkout -b feature/amazing-feature
  3. Commit: git commit -m 'Add amazing feature'
  4. Push: git push origin feature/amazing-feature
  5. Open a Pull Request

Guidelines: maintain 90%+ coverage, match existing code style, zero analyzer warnings, no new dependencies without discussion.


License #

MIT — see LICENSE

Copyright (c) 2026

1
likes
0
points
124
downloads

Documentation

Documentation

Publisher

unverified uploader

Weekly Downloads

A Riverpod debugging and state-inspection package that records every provider update, tracks dependencies, visualizes state changes, and supports time-travel debugging.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_riverpod, logger

More

Packages that depend on riverpod_timeline