Árbol de Rutas — GoRouter Configuration
Rutas independientes (fuera del Shell)
/onboarding
OnboardingScreen · Acceso sin auth
* (error)
ErrorScreen · Ruta no encontrada
↓ StatefulShellRoute.indexedStack ↓
/home
HomeScreen
Dashboard · resumen diario IA
/workouts
WorkoutsScreen
/workouts/:id
WorkoutDetailScreen
?week=N (query param)
/nutrition
NutritionScreen
/nutrition/:id
NutritionDetailScreen
/profile
ProfileScreen
Stats · Ajustes · Logout
Implementación — GoRouter Core
main.dart
router.dart
shell_widget.dart
// cultivafit/lib/main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
void main() {
usePathUrlStrategy(); // Elimina '#' en URLs web → cultivafit.app/workouts/123
runApp(const CultivaFitApp());
}
final GoRouter _router = GoRouter(
initialLocation: '/home',
debugLogDiagnostics: true,
redirect: (context, state) {
final isAuth = authState.isAuthenticated;
if (!isAuth && state.matchedLocation != '/onboarding') return '/onboarding';
if (isAuth && state.matchedLocation == '/onboarding') return '/home';
return null;
},
refreshListenable: authState, // Refresca rutas al cambiar auth
routes: [
GoRoute(path: '/onboarding', builder: OnboardingScreen),
StatefulShellRoute.indexedStack(
builder: (ctx, state, shell) => CultivaFitShell(shell: shell),
branches: [
StatefulShellBranch(routes: [GoRoute(path: '/home', ...),]),
StatefulShellBranch(routes: [GoRoute(path: '/workouts',
routes: [GoRoute(path: ':id', ...)],
)]),
StatefulShellBranch(routes: [GoRoute(path: '/nutrition',
routes: [GoRoute(path: ':id', ...)],
)]),
StatefulShellBranch(routes: [GoRoute(path: '/profile', ...),]),
],
),
],
errorBuilder: (ctx, state) => ErrorScreen(error: state.error),
);
Deep Linking — Configuración por Plataforma
Métodos de Navegación Programática
context.go()
Reemplaza el stack completo con la ruta destino. Ideal para navegación principal entre secciones.
context.go('/workouts/fuerza-lunes-001');
context.push()
Apila la ruta sobre el stack actual. Mantiene historial de navegación para poder volver.
context.push('/nutrition/plan-semana-003');
context.goNamed()
Navega por nombre de ruta con pathParameters y queryParameters seguros. Recomendado.
context.goNamed('workout-detail',
pathParameters: {'id': 'hiit-002'},
queryParameters: {'week': '3'});
context.pop()
Vuelve a la ruta anterior. Puede retornar un valor al destino (útil en modales).
context.pop(); // Volver sin valor
context.pop({'saved': true}); // Con retorno
Checklist de Implementación — CultivaFit
Configuración base
✓
Flutter create + flutter pub add go_router
✓
usePathUrlStrategy() en main()
✓
GoRouter con initialLocation: '/home'
✓
MaterialApp.router con routerConfig: _router
✓
AuthState como refreshListenable
Navegación anidada
✓
StatefulShellRoute.indexedStack configurado
✓
4 StatefulShellBranch (Home/Workouts/Nutrición/Perfil)
✓
ScaffoldWithNavBar con NavigationBar Material 3
✓
Sub-rutas :id en workouts y nutrition
Deep Linking iOS
✓
FlutterDeepLinkingEnabled: true en Info.plist
✓
applinks:cultivafit.app en entitlements
✓
AASA publicado con CULTV5.com.cultivaia.cultivafit
✓
Validado con xcrun simctl openurl
Deep Linking Android
✓
Intent filter con autoVerify="true" en Manifest
✓
assetlinks.json con SHA-256 del keystore
✓
Validado con adb shell am start
✓
Package com.cultivaia.cultivafit verificado