Redirects
GoRouter Modular delegates redirects to GoRouter. You can define global redirects (in configure) and per-route redirects (in ChildRoute / ModuleRoute).
Global Redirect
Runs on every navigation event. Use it for cross-cutting rules like authentication:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Modular.configure(
appModule: AppModule(),
initialRoute: '/',
redirect: (context, state) {
final loggedIn = AuthService.isLoggedIn;
if (!loggedIn) return '/login';
return null; // no redirect
},
);
runApp(AppWidget());
}- Return
nullto proceed normally. - Return a path string to redirect.
Per-Route Redirect
Runs before the page builder for a specific route:
ChildRoute(
'/dashboard',
child: (context, state) => const DashboardPage(),
redirect: (context, state) {
if (!AuthService.isAdmin) return '/';
return null;
},
)Redirect with Path Parameters
ChildRoute(
'/users/:id',
child: (context, state) => UserPage(id: state.pathParameters['id']!),
redirect: (context, state) {
final id = state.pathParameters['id'];
if (id == null || id.isEmpty) return '/users';
return null;
},
)Best Practices
- Use global redirect for auth — One place for authentication checks.
- Use per-route redirect for guards — Role checks, feature flags, data validation.
- Avoid redirect loops — Ensure the target does not redirect back to the source.
- Use absolute paths — Always redirect to full paths (e.g.
/login, notlogin).
For more details, see the GoRouter redirect documentation (opens in a new tab).