Grand Central Station: Why BLoC, Riverpod, and BlocSignal Are Now True Peers Randal L. Schwartz announced the release of bloc_signals_bloc and a major update to bloc_signals_riverpod, making BLoC, Riverpod, and BlocSignal first-class, bidirectional peers in Flutter state management. The new packages allow seamless, type-safe, lifecycle-managed integration between the three state containers, eliminating the need for risky rewrites or clunky adapter boilerplate. By Randal L. Schwartz, and a few million TPU cycles Motto: "With the rigor of Bloc and the flex and speed of Signal" If you have spent any time in the Flutter community over the past eight years, you have witnessed the great "State Management Wars." On one track sat Classic BLoC : strict, battle-tested, enterprise-grade, but heavily reliant on asynchronous Dart Stream microtasks. On an adjacent track sat Riverpod : offering compile-time safety and declarative dependency graph plumbing, but steering increasingly toward mandatory code generation and build runner iteration tax. On the newest high-speed track arrived Signals : offering raw sub-microsecond synchronous reactivity and fine-grained UI rebuilding. For years, choosing a state management library felt like choosing an isolated railroad network. If an engineering team built their core application with flutter bloc or flutter riverpod and wanted to take advantage of synchronous Signals for a new high-frequency feature, conventional wisdom dictated a painful choice: either undertake a risky, multi-month rewrite or suffer through clunky, second-class adapter boilerplate . Traditional "interop" packages in our ecosystem have almost always been an afterthoughtβ€”awkward, leaky wrappers designed to tolerate legacy code until someone finds the budget to delete it. Today, with the release of bloc signals bloc and a major update to bloc signals riverpod BLoC, Riverpod, and BlocSignal are no longer competing silos . They are first-class, bidirectional peers . Imagine walking into a majestic railway terminalβ€”vaulted glass arches overhead, golden sunbeams cutting through the air, and railway block signal gantries glowing bright green. Pulling up to the platforms side by side on three parallel steel tracks are three distinct locomotives: πŸš‚ Track 1: Classic BLoC The Steam Locomotive ─────┐ β”‚ 🚚 Track 2: Riverpod The Heavy Freight Hauler ──────┼──► Grand Central State Terminal ◄──► Synchronous Signals β”‚ πŸš„ Track 3: BlocSignal The High-Speed Maglev β”€β”€β”€β”€β”€β”€β”€β”˜ In Grand Central Terminal, the tracks do not collide, and no train is treated as second-class rolling stock . Platforms sit adjacent to each other. Passengers state, events, actions walk across the concourse between trains with zero baggage check fees, zero customs delays, and zero microtask penalties . In most architectures, adapting one state container to another requires wrapping everything in custom StreamController instances, registering manual listener callbacks, and remembering to clean up disposers to prevent memory leaks. Under BlocSignal , peer integration is completely bidirectional, lifecycle-managed, and type-safe : | From Target βž” To Target | How It Works | Developer Ergonomics | |---|---|---| Classic BLoC βž” BlocSignal | classicBloc.toBlocSignal | Exposes synchronous .state signal + forwards .add event | Classic Cubit βž” CubitSignal | classicCubit.toBlocSignal | Exposes synchronous .state signal + typed .cubit methods | Riverpod Provider βž” BlocSignal | provider.toBlocSignal ref | Exposes synchronous .state signal + typed .notifier methods + auto-disposal | BlocSignal βž” Classic BLoC | blocSignal.toClassicBloc | Direct drop-in for legacy flutter bloc BlocBuilder / BlocListener | CubitSignal βž” Classic Cubit | cubitSignal.toClassicCubit | Direct drop-in for legacy flutter bloc widgets | BlocSignal / CubitSignal βž” Riverpod | blocSignal.toProvider | Direct drop-in for Riverpod ref.watch and ref.read | Riverpod AsyncValue ↔ Signals AsyncState | .toAsyncState / .toAsyncValue | Seamless mapping across sealed loading/error/data states | Let's put this into practice with a concrete example. What does it look like when all three state engines work together in a single Flutter screen? Here is a complete, runnable Flutter app where a Classic BLoC , a Riverpod Notifier , and a Modern CubitSignal live side by side. Each manages its own domain state, yet they compose synchronously into a unified Grand Total using a single computed signal in under 65 lines of code : import 'package:flutter/material.dart'; import 'package:flutter riverpod/flutter riverpod.dart'; import 'package:bloc/bloc.dart' as bloc lib; import 'package:bloc signals/bloc signals.dart'; import 'package:bloc signals bloc/bloc signals bloc.dart'; import 'package:bloc signals riverpod/bloc signals riverpod.dart'; import 'package:signals flutter/signals flutter.dart'; // πŸš‚ 1. CLASSIC BLOC: The Steam Engine Explicit Event - State class ClassicCounterBloc extends bloc lib.Bloc