Routes & Modules
Redirects

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 null to 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

  1. Use global redirect for auth — One place for authentication checks.
  2. Use per-route redirect for guards — Role checks, feature flags, data validation.
  3. Avoid redirect loops — Ensure the target does not redirect back to the source.
  4. Use absolute paths — Always redirect to full paths (e.g. /login, not login).

For more details, see the GoRouter redirect documentation (opens in a new tab).