62 lines
2.0 KiB
Cheetah
62 lines
2.0 KiB
Cheetah
---
|
|
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<HomeRoute>(path: '/')
|
|
class HomeRoute extends GoRouteData {
|
|
const HomeRoute();
|
|
@override Widget build(BuildContext ctx, GoRouterState state) => const HomeScreen();
|
|
}
|
|
|
|
@TypedGoRoute<ProductRoute>(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
|