--- description: "GoRouter conventions for {{PROJECT_NAME}}" alwaysApply: true --- # GoRouter Standards — {{PROJECT_NAME}} ## Typed routes (mandatory) ```dart // Define typed routes — never use string paths directly in navigation calls @TypedGoRoute(path: '/') class HomeRoute extends GoRouteData { const HomeRoute(); @override Widget build(BuildContext ctx, GoRouterState state) => const HomeScreen(); } @TypedGoRoute(path: '/products/:id') class ProductRoute extends GoRouteData { final String id; const ProductRoute({required this.id}); @override Widget build(BuildContext ctx, GoRouterState state) => ProductScreen(id: id); } // Navigate with type safety const ProductRoute(id: product.id).go(context); // ✅ context.go('/products/${product.id}'); // ❌ — don't do this ``` ## Auth guard ```dart // Redirect logic in router config redirect: (context, state) { final isLoggedIn = ref.read(authProvider).isAuthenticated; final isLoginRoute = state.matchedLocation == '/login'; if (!isLoggedIn && !isLoginRoute) return '/login'; if (isLoggedIn && isLoginRoute) return '/'; return null; }, ``` ## Shell routes for bottom navigation ```dart ShellRoute( builder: (ctx, state, child) => MainScaffold(child: child), routes: [ GoRoute(path: '/home', builder: (_, __) => const HomeScreen()), GoRoute(path: '/search', builder: (_, __) => const SearchScreen()), GoRoute(path: '/profile', builder: (_, __) => const ProfileScreen()), ], ) ``` ## Deep links - Register URL schemes in `Info.plist` (iOS) and `AndroidManifest.xml` - Test deep links with: `adb shell am start -a android.intent.action.VIEW -d "app://{{PACKAGE_ID}}/products/123"` - Handle `GoRouter.of(context).routerDelegate.currentConfiguration` for dynamic links ## Rules - **NEVER** use `Navigator.push/pop` — use `context.go()`, `context.push()`, `context.pop()` - All routes declared in one file: `lib/core/routing/app_router.dart` - `BlocProvider`s for route-level blocs created inside the `builder` of each route