Routes & Modules
Modules are the building blocks of a GoRouter Modular app. Each module encapsulates its own routes, dependencies, and business logic.
Module Structure
class ProductsModule extends Module {
@override
FutureBinds binds(Injector i) {
i.addSingleton<ProductsController>((i) => ProductsController());
}
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (_, __) => ProductsPage()),
ChildRoute('/details/:id', child: (_, state) =>
ProductDetailPage(id: state.pathParameters['id']!)),
];
}Route Types
ChildRoute
Defines a single page within a module:
ChildRoute('/', child: (context, state) => HomePage())
ChildRoute('/profile', child: (context, state) => ProfilePage())
ChildRoute('/user/:id', child: (context, state) =>
UserPage(id: state.pathParameters['id']!))ModuleRoute
Delegates a path to a separate module:
ModuleRoute('/products', module: ProductsModule())
ModuleRoute('/auth', module: AuthModule())ShellModularRoute
Wraps child routes with a shared layout (e.g. a navigation rail). All children share the same navigator:
ShellModularRoute(
builder: (context, state, child) => MainLayout(child: child),
routes: [
ModuleRoute('/home', module: HomeModule()),
ModuleRoute('/settings', module: SettingsModule()),
],
)StatefulShellModularRoute
For bottom navigation bars and tabs that preserve state across branches. Each branch gets its own navigator backed by an IndexedStack:
StatefulShellModularRoute(
builder: (context, state, navigationShell) => AppShell(
navigationShell: navigationShell,
),
branches: [
ModularBranch(module: HomeModule()),
ModularBranch(module: SearchModule()),
ModularBranch(routes: [
ChildRoute('/profile', child: (_, __) => ProfilePage()),
]),
],
)See Shell Routes for detailed documentation.
Module Nesting
Modules can contain other modules for hierarchical navigation:
class ShopModule extends Module {
@override
List<ModularRoute> get routes => [
ChildRoute('/', child: (_, __) => ShopHomePage()),
ModuleRoute('/products', module: ProductsModule()),
ModuleRoute('/cart', module: CartModule()),
];
}The resulting paths are:
/shop— ShopHomePage/shop/products— ProductsModule entry point/shop/cart— CartModule entry point
Route Parameters
// Path parameters
ChildRoute('/user/:id', child: (_, state) =>
UserPage(id: state.pathParameters['id']!))
// Navigate
context.go('/user/123');Page Transitions
Attach transitions at the module or route level:
ModuleRoute('/home', module: HomeModule(),
transition: GoTransitions.fadeUpwards,
duration: Duration(milliseconds: 300))See Page Transitions for all available transitions.
Common Patterns
Feature Module
class AuthModule extends Module {
@override
FutureBinds binds(Injector i) {
i.addSingleton<AuthController>((i) => AuthController());
}
@override
List<ModularRoute> get routes => [
ChildRoute('/login', child: (_, __) => LoginPage()),
ChildRoute('/register', child: (_, __) => RegisterPage()),
ChildRoute('/forgot-password', child: (_, __) => ForgotPasswordPage()),
];
}App Module
class AppModule extends Module {
@override
FutureBinds binds(Injector i) {
i.addSingleton<AppConfig>((i) => AppConfig());
}
@override
List<ModularRoute> get routes => [
ModuleRoute('/', module: HomeModule()),
ModuleRoute('/products', module: ProductsModule()),
ModuleRoute('/auth', module: AuthModule()),
ModuleRoute('/settings', module: SettingsModule()),
];
}Best Practices
- One module per feature — Keep related routes and dependencies together.
- Use
ModuleRoutefor features — Isolate each feature in its own module. - Use
ChildRoutefor pages — Individual pages within a module. - Keep modules small — Easier to maintain and test.
- Plan your route hierarchy — Think about your app's navigation flow before coding.