Bidev
IntermediateNavigation & Routing

How does go_router simplify navigation in Flutter?

// short answer

go_router lets you define your app's routes as a declarative table mapping URL paths to pages, handling deep linking, web URL sync, and nested/shell routes without writing raw Navigator 2.0 boilerplate.

You define a GoRouter with a list of GoRoute entries, each specifying a path and a builder returning the page widget for that path — including path parameters (/users/:id) and query parameters, both accessible via state. Navigating is as simple as context.go('/users/5') or context.push('/settings'), and go_router keeps the browser URL in sync automatically on Flutter Web.

It also supports ShellRoute for persistent UI (like a bottom nav bar that stays while inner content changes) and redirect logic (e.g. redirecting to login if unauthenticated), both notoriously fiddly to implement correctly with raw Navigator 2.0.

// code example

final router = GoRouter(
  routes: [
    GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
    GoRoute(
      path: '/users/:id',
      builder: (context, state) {
        final id = state.pathParameters['id']!;
        return UserScreen(userId: id);
      },
    ),
  ],
);

// Navigate
context.go('/users/5');

// common mistakes

  • ×Mixing go_router navigation with raw Navigator.push in the same app inconsistently, causing confusing back-stack behavior.
  • ×Not using redirect for auth guarding and instead manually checking auth state in every screen's initState.