go-router

Declarative URL-based routing for Flutter using the Router API. Use when implementing navigation between screens, deep links, authentication guards, parameterized routes, shell routes with nested navigation, and web routing in Flutter apps.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "go-router" with this command: npx skills add tobiasbentin/go-router

Go Router

GoRouter is a declarative routing package for Flutter that uses the Router API to provide convenient URL-based navigation.

Core Concepts

1. Router Configuration

Define routes as a list of GoRoute objects:

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

2. Navigation

// Simple navigation
context.go('/details');

// With parameters
context.go('/user/123');

// Named navigation (requires name parameter)
context.goNamed('user', pathParameters: {'id': '123'});

// Push (adds to stack)
context.push('/modal');

// Replace current route
context.replace('/new');

// Go back
context.pop();

// With query parameters
context.go('/search?q=flutter');

3. Route Parameters

Path parameters use : prefix:

GoRoute(
  path: '/user/:id/posts/:postId',
  builder: (context, state) {
    final userId = state.pathParameters['id']!;
    final postId = state.pathParameters['postId']!;
    return PostScreen(userId: userId, postId: postId);
  },
)

Query parameters are accessed via state.uri.queryParameters:

GoRoute(
  path: '/search',
  builder: (context, state) {
    final query = state.uri.queryParameters['q'] ?? '';
    return SearchScreen(query: query);
  },
)

Common Patterns

Pattern 1: Authentication Guard with Redirection

final routerProvider = Provider<GoRouter>((ref) {
  final auth = ref.watch(authProvider);
  
  return GoRouter(
    initialLocation: '/',
    redirect: (context, state) {
      final isLoggedIn = auth.isLoggedIn;
      final isAuthRoute = state.matchedLocation == '/login';
      
      if (!isLoggedIn && !isAuthRoute) {
        return '/login';
      }
      if (isLoggedIn && isAuthRoute) {
        return '/';
      }
      return null;
    },
    routes: [
      GoRoute(path: '/login', builder: (_, __) => const LoginScreen()),
      GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
    ],
  );
});

Pattern 2: ShellRoute for Bottom Navigation

GoRouter(
  routes: [
    ShellRoute(
      builder: (context, state, child) {
        return ScaffoldWithNavBar(child: child);
      },
      routes: [
        GoRoute(
          path: '/',
          builder: (_, __) => const HomeScreen(),
        ),
        GoRoute(
          path: '/settings',
          builder: (_, __) => const SettingsScreen(),
        ),
      ],
    ),
  ],
)

Pattern 3: StatefulShellRoute for Nested Navigation

StatefulShellRoute(
  branches: [
    StatefulShellBranch(
      routes: [GoRoute(path: '/feed', builder: (_, __) => FeedScreen())],
    ),
    StatefulShellBranch(
      routes: [GoRoute(path: '/profile', builder: (_, __) => ProfileScreen())],
    ),
  ],
)

Pattern 4: Custom Page Transitions

GoRoute(
  path: '/details',
  pageBuilder: (context, state) => const MaterialPage(
    child: DetailsScreen(),
  ),
  // Or custom transition
  pageBuilder: (context, state) => CustomTransitionPage(
    child: const DetailsScreen(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      return FadeTransition(
        opacity: CurveTween(curve: Curves.easeInOut).animate(animation),
        child: child,
      );
    },
  ),
)

Pattern 5: Error Handling

GoRouter(
  errorBuilder: (context, state) {
    return ErrorScreen(error: state.error);
  },
  // Or handle 404
  errorPageBuilder: (context, state) => MaterialPage(
    child: NotFoundScreen(path: state.uri.path),
  ),
)

Pattern 6: Type-Safe Routes (Go Router 14+)

Define typed routes:

part 'app_routes.g.dart';

@TypedGoRoute<HomeRoute>(path: '/')
class HomeRoute extends GoRouteData {
  @override
  Widget build(BuildContext context, GoRouterState state) {
    return const HomeScreen();
  }
}

@TypedGoRoute<UserRoute>(path: '/user/:id')
class UserRoute extends GoRouteData {
  final String id;
  const UserRoute({required this.id});
  
  @override
  Widget build(BuildContext context, GoRouterState state) {
    return UserScreen(id: id);
  }
}

Route State

Access route information in builders:

GoRoute(
  path: '/details',
  builder: (context, state) {
    // Path: state.uri.path
    // Query params: state.uri.queryParameters
    // Extra data: state.extra (passed via context.go('/details', extra: data))
    return DetailsScreen(
      path: state.uri.path,
      data: state.extra as MyData?,
    );
  },
)

Navigation Helper Methods

// Extension for cleaner navigation
extension NavigationHelpers on BuildContext {
  void goHome() => go('/');
  void goUser(String id) => go('/user/$id');
  void pushModal(Widget screen) => push('/modal', extra: screen);
}

// Usage
context.goHome();
context.goUser('123');

Web Support

Enable web URL handling:

GoRouter(
  // Handles browser back/forward
  // URL updates automatically
  initialLocation: '/',
  // For base href in web
  routerNeglect: true, // Disable browser history
)

// Access current route
final currentRoute = GoRouter.of(context).routeInformationProvider.value.uri.path;

Route Observers

GoRouter(
  observers: [RouteObserver()],
  navigatorBuilder: (context, state, child) {
    // Wrap all routes
    return SomeWrapper(child: child);
  },
)

Testing

testWidgets('navigates correctly', (tester) async {
  await tester.pumpWidget(
    MaterialApp.router(
      routerConfig: _router,
    ),
  );
  
  // Find and tap button
  await tester.tap(find.text('Go to details'));
  await tester.pumpAndSettle();
  
  // Verify navigation
  expect(find.text('Details'), findsOneWidget);
});

Code Generation

For type-safe routes with code generation:

dart run build_runner build

Generates:

  • $route constant for route location
  • Parameter classes for typed routes

Deep Linking

Configure Android & iOS for deep links, then handle in GoRouter:

GoRouter(
  routes: [
    GoRoute(
      path: '/product/:id',
      builder: (context, state) {
        // Handles myapp.com/product/123
        // and app://product/123
        return ProductScreen(id: state.pathParameters['id']!);
      },
    ),
  ],
)

Navigation Without Context

// Store router reference
final GoRouter router = GoRouter(...);

// Navigate without context
router.go('/home');
router.push('/modal');
router.pop();

See BEST_PRACTICES.md for architecture patterns.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Ai Competitor Analyzer

提供AI驱动的竞争对手分析,支持批量自动处理,提升企业和专业团队分析效率与专业度。

Registry SourceRecently Updated
General

Ai Data Visualization

提供自动化AI分析与多格式批量处理,显著提升数据可视化效率,节省成本,适用企业和个人用户。

Registry SourceRecently Updated
General

Ai Cost Optimizer

提供基于预算和任务需求的AI模型成本优化方案,计算节省并指导OpenClaw配置与模型切换策略。

Registry SourceRecently Updated