Riverpod to BlocSignal: Incremental Migration and…
    Neura Market
    Neura Market
    /CoPilot
    Marketplace
    Directories
    Resources
    CoPilot
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeekCoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityPluginsTrending
    CoPilotBlogRiverpod to BlocSignal: Incremental Migration and Zero-Codegen Signals for Flutter
    Back to Blog
    Riverpod to BlocSignal: Incremental Migration and Zero-Codegen Signals for Flutter
    flutter

    Riverpod to BlocSignal: Incremental Migration and Zero-Codegen Signals for Flutter

    Randal L. Schwartz August 12, 2026
    0 views

    Learn how to trial or incrementally migrate from Riverpod to BlocSignal with zero code generation, fine-grained signal graph reactivity, and bidirectional interop.


    title: Riverpod to BlocSignal: Incremental Migration and Zero-Codegen Signals for Flutter published: true description: Learn how to trial or incrementally migrate from Riverpod to BlocSignal with zero code generation, fine-grained signal graph reactivity, and bidirectional interop. tags: flutter, dart, riverpod, statemanagement canonical_url: https://blocsignal.dev series: BlocSignal Architecture & Practice

    Introduction: Combining Riverpod Safety with Zero Codegen

    If you've been building Flutter apps with Riverpod, you already know the joy of compile-time provider safety, auto-disposal, and synchronous notification propagation via ProviderListenable. Riverpod fundamentally raised the bar for Flutter state management.

    However, as projects grow, many Riverpod developers run into familiar friction points:

    • Code Generation Overhead: Depending heavily on riverpod_generator and waiting on build_runner watches during rapid UI iteration.
    • Complex Provider Trees: Managing nested ProviderScope overrides and .family cache eviction policies when scaling large teams.
    • All-or-Nothing Migration Concerns: Wanting to trial new reactive primitives or event-driven BLoC architectures without rewriting an entire codebase.

    What if you could combine the compile-time safety and synchronous reactivity you love in Riverpod with zero code generation, fine-grained signal graph reactivity, and the ability to trial or migrate incrementally screen-by-screen?

    Enter BlocSignal and bloc_signals_riverpod.


    The Core Ergonomics: Riverpod Notifier vs. CubitSignal

    Let's compare the classic Todos application—one of the benchmark examples in the official Riverpod monorepo—ported directly to BlocSignal.

    The Riverpod Approach (Requires @riverpod & build_runner)

    In modern Riverpod, creating a todo list with reactive filtering typically involves a generated Notifier and separate provider getters or ref.watch selectors:

    @riverpod
    class TodoList extends _$TodoList {
      @override
      List<Todo> build() => const [];
    
      void addTodo(String description) {
        state = [...state, Todo(id: DateTime.now().toString(), description: description)];
      }
    
      void toggle(String id) {
        state = [
          for (final todo in state)
            if (todo.id == id) todo.copyWith(completed: !todo.completed) else todo
        ];
      }
    }
    
    // Derived filter provider
    @riverpod
    List<Todo> filteredTodos(Ref ref) {
      final todos = ref.watch(todoListProvider);
      final filter = ref.watch(todoFilterProvider);
      return switch (filter) {
        TodoFilter.all => todos,
        TodoFilter.active => todos.where((t) => !t.completed).toList(),
        TodoFilter.completed => todos.where((t) => t.completed).toList(),
      };
    }
    

    The BlocSignal Approach (100% Pure Dart 3, No Codegen)

    With BlocSignal, your state container is a standard handwritten Dart class (CubitSignal<List<Todo>>). Reactive derivations like filteredTodos and uncompletedCount are declared inline using signals computed():

    import 'package:bloc_signals/bloc_signals.dart';
    import 'package:flutter/foundation.dart';
    import 'package:signals_core/signals_core.dart';
    
    class TodosCubit extends CubitSignal<List<Todo>> {
      // Pass `equals: listEquals` to enforce value-based list equality for state de-duplication!
      TodosCubit([List<Todo> initialTodos = const []])
          : super(initialState: initialTodos, equals: listEquals) {
        // 1. Reactive filter signal
        filter = signal(TodoFilter.all);
    
        // 2. Synchronously derived computed signals
        filteredTodos = computed(() {
          return switch (filter.value) {
            TodoFilter.all => stateValue,
            TodoFilter.active => stateValue.where((t) => !t.completed).toList(),
            TodoFilter.completed => stateValue.where((t) => t.completed).toList(),
          };
        });
    
        uncompletedCount = computed(() => stateValue.where((t) => !t.completed).length);
      }
    
      late final Signal<TodoFilter> filter;
      late final ReadonlySignal<List<Todo>> filteredTodos;
      late final ReadonlySignal<int> uncompletedCount;
    
      void addTodo(String description) {
        emit([...stateValue, Todo(id: DateTime.now().toString(), description: description)]);
      }
    
      void toggle(String id) {
        emit([
          for (final todo in stateValue)
            if (todo.id == id) todo.copyWith(completed: !todo.completed) else todo
        ]);
      }
    
      void setFilter(TodoFilter newFilter) => filter.value = newFilter;
    
      @override
      Future<void> close() async {
        filter.dispose();
        filteredTodos.dispose();
        uncompletedCount.dispose();
        await super.close();
      }
    }
    

    What Changed?

    1. No build_runner: No .g.dart generated files, no background watchers, no build step delays.
    2. Built-In Custom Equality (equals: listEquals): Because Dart List instances don't override == by default, passing equals: listEquals configures the underlying signal graph to de-duplicate state emissions based on list content equality.
    3. Fine-Grained Signal Graph: Updates to filter.value or calling emit(...) re-evaluate computed() derivations synchronously and notify only dependent widgets.
    4. Explicit Container Lifecycles: Disposing the cubit disposes its internal signals automatically.

    Zero Risk: Incremental Trial & Bidirectional Interop

    You do not need to rewrite your application to try BlocSignal. With the bloc_signals_riverpod package, you can seamlessly bridge the two frameworks in both directions.

    dependencies:
      bloc_signals: ^1.0.0
      bloc_signals_flutter: ^1.0.0
      bloc_signals_riverpod: ^1.0.0
    

    Option A: Expose a BlocSignal / CubitSignal to Existing Riverpod Widgets

    Want to write a new feature or state controller with BlocSignal, but keep your existing Riverpod UI layer (ConsumerWidget, WidgetRef)?

    Simply call .toProvider():

    import 'package:bloc_signals_riverpod/bloc_signals_riverpod.dart';
    
    // Create your new BlocSignal or CubitSignal
    final todosCubit = TodosCubit();
    
    // Convert it directly into a Riverpod NotifierProvider!
    final todosProvider = todosCubit.toProvider();
    
    // Now consume it anywhere in existing Riverpod widgets:
    class LegacyRiverpodWidget extends ConsumerWidget {
      const LegacyRiverpodWidget({super.key});
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        // Rebuilds reactively whenever todosCubit emits!
        final todos = ref.watch(todosProvider);
    
        return ListView.builder(
          itemCount: todos.length,
          itemBuilder: (context, i) => Text(todos[i].description),
        );
      }
    }
    

    Option B: Adapt an Existing Riverpod Provider into BlocSignal

    Have a legacy Riverpod provider that you need to read from a new BlocSignalBuilder widget?

    Use .toBlocSignal(ref):

    import 'package:bloc_signals_riverpod/bloc_signals_riverpod.dart';
    
    class NewFeatureWidget extends ConsumerWidget {
      const NewFeatureWidget({super.key});
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        // Adapt any Riverpod ProviderListenable into a BlocSignal container!
        // Automatically binds ref.onDispose to close the container when disposed.
        final todosBloc = legacyRiverpodProvider.toBlocSignal(ref);
    
        return BlocSignalBuilder<BlocSignalBase<List<Todo>>, List<Todo>>(
          bloc: todosBloc,
          builder: (context, todos) {
            return ListView.builder(
              itemCount: todos.length,
              itemBuilder: (context, i) => Text(todos[i].description),
            );
          },
        );
      }
    }
    

    Converting AsyncValue <-> AsyncState

    bloc_signals_riverpod also provides extension methods to map seamlessly between Riverpod's AsyncValue and Signals' AsyncState:

    // Riverpod AsyncValue to Signals AsyncState
    final asyncState = riverpodAsyncValue.toAsyncState();
    
    // Signals AsyncState to Riverpod AsyncValue
    final asyncValue = signalsAsyncState.toAsyncValue();
    

    Explore the Official Riverpod Ports on blocsignal.dev

    To prove the DX gains and side-by-side equivalence, we've ported canonical state management examples directly from the official rrousselGit/riverpod monorepo into the BlocSignal open-source repository:

    1. 📝 Riverpod Todos (examples/riverpod_todos):
      • Replaces @riverpod codegen and Notifier with CubitSignal<List<Todo>> and synchronous computed() signals for reactive filter tabs and stats.
    2. 🔍 Pub.dev Package Search (examples/riverpod_pub):
      • Replaces Riverpod AsyncNotifier with BlocSignal and a streamless restartable() event transformer that automatically cancels in-flight API requests on keypresses without Rx streams.
    3. 🦸 Marvel Character Browser (examples/riverpod_marvel):
      • Demonstrates API pagination, character search, and widget tree scoping via BlocSignalProvider.value.

    Explore all 20 side-by-side benchmark ports across BLoC, Signals, and Riverpod live at blocsignal.dev/#ported-examples!


    Built-In AI Agent Skills for Automated Migration

    If you use AI coding assistants like Antigravity, Gemini, Cursor, or GitHub Copilot, BlocSignal publishes a dedicated Agent Plugin skill bundle (riverpod_migration.md).

    When your AI assistant inspects a project with BlocSignal skills enabled, it automatically understands:

    • How to map StateNotifierProvider / NotifierProvider to CubitSignal;
    • How to preserve auto-disposal and cancellation contracts;
    • How to refactor ConsumerWidget rebuild boundaries to BlocSignalBuilder or SignalBuilder;
    • How to apply bloc_signals_riverpod interop adapters during multi-phase refactoring.

    Summary

    You don't need to throw away your existing architecture to enjoy the speed, simplicity, and zero-codegen elegance of reactive signals.

    With bloc_signals_riverpod, you can trial BlocSignal on a single screen today, bridge your existing Riverpod providers seamlessly, and upgrade your developer experience at your own pace.

    • 🌐 Website & Comparison Benchmarks: blocsignal.dev
    • 📦 Pub.dev Packages: bloc_signals | bloc_signals_flutter | bloc_signals_riverpod
    • 🐙 GitHub Repository: RandalSchwartz/BlocSignal

    Tags

    flutterdartriverpodstatemanagement

    Comments

    More Blog

    View all
    Reviving Open Source Giants: How I Brought Weave Scope Back with Multi-Platform Docker Support in One Afternoon Using Antigravityopensource

    Reviving Open Source Giants: How I Brought Weave Scope Back with Multi-Platform Docker Support in One Afternoon Using Antigravity

    How to rescue abandoned open-source projects, modernize build systems, and generate multi-architecture Docker images (x86_64, ARM64) in a single afternoon with Antigravity.

    M
    Mario Ezquerro
    [Dev Log][Python] Create short videos from photos and clips with Gemini 3.7 Flash: ReelCraftai

    [Dev Log][Python] Create short videos from photos and clips with Gemini 3.7 Flash: ReelCraft

    Preface: It all started with a misunderstanding. I noticed a new page in the Gemini API...

    E
    Evan Lin
    Dart 3.13 Primary Constructors + BlocSignal: Boilerplate-Free Reactive Architectureflutter

    Dart 3.13 Primary Constructors + BlocSignal: Boilerplate-Free Reactive Architecture

    Discover how Dart 3.13 primary constructors, 'this' constructor bodies, and constructor shorthands transform BlocSignal into the cleanest state management architecture in Flutter.

    R
    Randal L. Schwartz
    Running Gemma 4 on EC2 G5g: Graviton2 AMD with NVIDIA GPUaws

    Running Gemma 4 on EC2 G5g: Graviton2 AMD with NVIDIA GPU

    A field report on serving Gemma 4 E2B under vLLM on AWS G5g — the only aarch64 + SM 7.5 hardware there is. No published build covers that combination, AWS quietly solves half of it, and the thing that actually blocks you is 64 KiB of shared memory.

    X
    xbill
    My (not so pretty) journey in techdiscuss

    My (not so pretty) journey in tech

    Ever since I joined the platform, I wanted to post about a topic I was really passionate about....

    I
    isha singh
    I Stopped Trusting AI Agents With Tools. So I Built a Gatekeeper.ai

    I Stopped Trusting AI Agents With Tools. So I Built a Gatekeeper.

    Update 08/15 0.2.0 Released github.com/deghosal-2026/agent-tooltrust · pip install agent-tooltrust...

    D
    Debashish Ghosal

    Stay up to date

    Get the latest CoPilot prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for CoPilot and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this CoPilot resource

    • Extract Text from Images & PDFs via Telegram with Mistral OCR to Markdownn8n · $24.99 · Related topic
    • Write a WordPress Post with AI (Starting from a Few Keywords)n8n · $24.99 · Related topic
    • Microsoft Outlook AI Email Assistant with Contact Support from Monday and Airtablen8n · $14.99 · Related topic
    • Answer Code of Conduct Questions in Slack with GPT-4 & RAGE Technologyn8n · $14.99 · Related topic
    Browse all workflows