← ClaudeAtlas

navigation-and-routinglisted

Enforces one app-wide GoRouter in lib/routing/ wired via MaterialApp.router, deep-linkable identity in path params never state.extra, context.go-vs-context.push discipline, redirect guards as pure functions driven by a Riverpod refreshListenable, StatefulShellRoute.indexedStack for branch-state-preserving BottomNavigationBar/NavigationRail shells, CustomTransitionPage transitions that respect reduced motion, PopScope (canPop/onPopInvokedWithResult) for unsaved-changes interception, and an errorBuilder 404 route. Use when adding routes, GoRoute, redirect, auth/onboarding gates, deep links, ShellRoute or nested navigation, bottom-nav/rail tab shells, page transitions, back-button/unsaved-changes handling, notification-payload-to-location mapping, typed routes, go_router_builder, or wiring go_router into app.dart.
zakariaf/CatchLaw · ★ 0 · AI & Automation · score 55
Install: claude install-skill zakariaf/CatchLaw
# Navigation and routing This skill owns app navigation with `go_router`. There is exactly ONE `GoRouter` for the app, defined in `lib/routing/`, and every screen is reachable by a URL. Navigation is a data structure (routes + a pure redirect), not a pile of imperative `Navigator.push` calls. Read the reference for the task at hand: - `references/go-router-config.md` — the single router, `context.go` vs `context.push`, path params vs `state.extra`, typed route helpers, `errorBuilder`/404. - `references/guards-and-redirects.md` — pure `redirect` functions, the Riverpod `refreshListenable`, auth + onboarding gates, avoiding redirect loops. - `references/shells-and-deep-links.md` — `StatefulShellRoute.indexedStack` for bottom-nav/rail shells, `CustomTransitionPage`, `PopScope`, and notification-payload → location mapping. Run `scripts/check_routing.sh` before a PR. ## Non-negotiable rules 1. **Exactly ONE `GoRouter`, built in `lib/routing/`, wired once via `MaterialApp.router` in `app.dart`.** Multiple routers fragment history, deep links, and back-button behaviour. The router is created behind a provider so guards can watch app state. 2. **Deep-linkable identity lives in PATH PARAMS, never in `state.extra`.** `extra` is a live Dart object: it is `null` on a cold start from a deep link and after process death / restoration. A screen that needs an id to rebuild must read it from `state.pathParameters` so the URL alone fully reconstructs the screen. 3. **`state.extra` is ONLY