Go Router Modular Banner

🧩 GoRouter Modular πŸ’‰

Dependency injection and route management

Perfect for micro-frontends and event-driven communication

Pub Version GitHub Stars License

GoRouter Modular simplifies Flutter development by implementing a modular architecture with GoRouter for route management 🧩 and supports per-module dependency injection with auto-dispose πŸ’‰.

Perfect for micro frontends and large-scale applications! πŸš€


Complete Documentation

DocumentaΓ§Γ£o

Contents

✨ Key Features

  • 🧩 Modular Architecture - Independent, reusable modules
  • πŸ’‰ Dependency Injection - Built-in DI with auto-dispose
  • πŸ›£οΈ GoRouter Integration - Type-safe and declarative navigation
  • 🎭 Event System - Event-driven communication between modules
  • πŸš€ Performance - Lazy loading and efficient memory management
  • πŸ›‘οΈ Type Safety - Fully type-safe with compile-time error detection

🧠 Why GoRouter Modular?

  • Real scalability: independent modules and lazy loading keep your app lightweight.
  • Clear organization: routes and injections live within their features, improving maintainability.
  • Dependency isolation: each module manages its own binds with automatic disposal.
  • Decoupled communication: built-in event system across modules.
  • Developer productivity: simple API on top of GoRouter without sacrificing flexibility.

⚑ Quick Start

πŸ“¦ Install

flutter pub add go_router_modular
dependencies:
  flutter:
    sdk: flutter
  go_router_modular: ^any

🧩 Create core files

lib/src/app_widget.dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';

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

  @override
  Widget build(BuildContext context) {
    return ModularApp.router(
      scrollBehavior: const MaterialScrollBehavior().copyWith(
        dragDevices: {
          PointerDeviceKind.touch,
          PointerDeviceKind.mouse,
        },
      ),
      title: 'Modular GoRoute Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}

lib/src/app_module.dart

import 'package:go_router_modular/go_router_modular.dart';

class AppModule extends Module {
  @override
  FutureOr<List<Bind<Object>>> binds() => [
   // Bind.singleton<HomeController>((i) => HomeController()),
  ];

  @override
  List<ModularRoute> get routes => [
   // ModuleRoute('/', child: (context, state) => HomeModule()),
  ];
}

πŸš€ Configure App

lib/main.dart

import 'package:flutter/material.dart';
import 'package:go_router_modular/go_router_modular.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Modular.configure(
    appModule: AppModule(), 
    initialRoute: "/",
    debugLogDiagnostics: true,
    debugLogDiagnosticsGoRouter: true,
  );
  runApp(AppWidget());
}

🧩 Module Example

class HomeModule extends Module {
  @override
  FutureOr<List<Bind<Object>>> binds() => [
    Bind.singleton<HomeController>((i) => HomeController()),
  ];

  @override
  List<ModularRoute> get routes => [
    ChildRoute('/', child: (context, state) => HomePage()),
    ChildRoute('/profile', child: (context, state) => ProfilePage()),
  ];
}

πŸ’‰ Dependency injection

Example of binds in the feature package:

// features/cart/lib/cart_module.dart
class CartModule extends Module {
  @override
  FutureOr<List<Bind<Object>>> binds() => [
    Bind.singleton<CartController>((i) => CartController()),
    Bind.factory<CartService>((i) => CartService()),
  ];

  @override
  List<ModularRoute> get routes => [
    ChildRoute('/', child: (context, state) => CartPage()),
  ];
}

How to use your injected dependencies

You can retrieve your dependencies in two main ways:

1. Using Modular.get<T>() anywhere:

final cartController = Modular.get<CartController>();

2. Using context.read<T>() inside a widget:

class CartPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final cartController = context.read<CartController>();
    // Use cartController as needed
    return ...;
  }
}
  • Use Modular.get<T>() for global access (not recommended inside widgets).
  • Use context.read<T>() for widget-specific access (recommended for UI).

🎭 Event System

class NotificationModule extends EventModule {
  @override
  void listen() {
    on<ShowNotificationEvent>((event, context) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(event.message)),
      );
    });
  }
}

// Fire event
ModularEvent.fire(ShowNotificationEvent('Hello!'));

πŸ›£οΈ Navigation Examples

Basic Navigation

// Navigate to a route
context.go('/profile');

// Push a new route
context.push('/settings');

// Go back
context.pop();
// Navigate with path parameters
context.go('/user/123');

// Navigate with query parameters
context.go('/search?q=flutter&category=all');

// Navigate with extra data
context.go('/product', extra: {'id': 456, 'name': 'Flutter Book'});

Async Navigation

ElevatedButton(
  onPressed: () async {
    // Show loading
    ModularLoader.show();
    
    // Perform async operation
    await Future.delayed(Duration(seconds: 2));
    
    // Navigate
    await context.goAsync('/heavy-page');
    
    // Hide loading
    ModularLoader.hide();
  },
  child: Text('Navigate with Loading'),
 ),


🀝 Contributing

Contributions are very welcome! Open an issue to discuss major changes and submit a PR with clear descriptions of the edits.

  • Follow the project conventions and keep docs updated.
  • Add small usage examples when introducing new features.

πŸ“„ License

This project is distributed under the MIT license. See LICENSE for details.


πŸŽ‰ Happy Coding with GoRouter Modular! πŸŽ‰

Transform your Flutter app into a scalable, modular masterpiece ✨

Contributors

Made with contrib.rocks


Libraries

go_router_modular