Getting Started With Flutter Navigation Using Go Router
Nov 20, 2025



Summary
Summary
Summary
Summary
This tutorial shows how to set up Go Router in Flutter, declare routes with parameters, perform navigation actions (go/push), manage state and redirects, and implement nested navigation with ShellRoute for tabbed or bottom-navigation apps. Go Router simplifies deep-linking and improves testability for mobile development.
This tutorial shows how to set up Go Router in Flutter, declare routes with parameters, perform navigation actions (go/push), manage state and redirects, and implement nested navigation with ShellRoute for tabbed or bottom-navigation apps. Go Router simplifies deep-linking and improves testability for mobile development.
This tutorial shows how to set up Go Router in Flutter, declare routes with parameters, perform navigation actions (go/push), manage state and redirects, and implement nested navigation with ShellRoute for tabbed or bottom-navigation apps. Go Router simplifies deep-linking and improves testability for mobile development.
This tutorial shows how to set up Go Router in Flutter, declare routes with parameters, perform navigation actions (go/push), manage state and redirects, and implement nested navigation with ShellRoute for tabbed or bottom-navigation apps. Go Router simplifies deep-linking and improves testability for mobile development.
Key insights:
Key insights:
Key insights:
Key insights:
Router Setup: Attach GoRouter to MaterialApp.router and centralize route definitions for predictable navigation.
Declarative Routes And Parameters: Use GoRouterState.params and queryParams inside route builders for deep linking.
Navigation Actions And State: Prefer context.go and context.push; use router.redirect for auth and conditional navigation.
Nested Navigation And Shell Routes: Use ShellRoute for persistent UI (tabs/bottom nav) with independent child stacks and URL-driven state.
Testing And Maintenance: Declarative routes and centralized redirects make navigation easy to unit test and maintain.
Introduction
Go Router is the recommended routing package for modern Flutter apps. It provides a declarative, URL-centered API that fits both mobile development and web targets. If you’re building a Flutter app that needs clean deep links, nested navigation, or predictable back-stack behavior, Go Router simplifies wiring routes into MaterialApp.router while making tests and state restoration easier.
Router Setup
Start by adding go_router to pubspec.yaml. Create a GoRouter instance and attach it to MaterialApp.router. Keep your routes centralized so navigation logic and URL structure are explicit.
final router = GoRouter(
routes: [
GoRoute(path: '/', builder: (c, s) => const HomePage()),
GoRoute(path: '/items/:id', builder: (c, s) => ItemPage(id: s.params['id']!)),
],
);
void main() => runApp(MaterialApp.router(routerConfig: router));This pattern replaces Navigator.push calls sprinkled across widgets. The router config controls parsing, redirection, and error handling in one place, improving maintainability for mobile development projects.
Declarative Routes And Parameters
Go Router is declarative: routes are defined as data, not as imperative push/pop calls. Path parameters and query parameters are available via the GoRouterState passed to route builders.
Access path parameters with state.params and query parameters with state.queryParams. Because builders receive state, UI can react directly to URL changes which is important for deep linking and testing.
Example: handling a route parameter and a search query.
GoRoute(
path: '/search/:category',
builder: (context, state) {
final category = state.params['category']!;
final q = state.queryParams['q'] ?? '';
return SearchPage(category: category, query: q);
},
),Avoid embedding navigation logic inside widgets. Keep route-to-widget mapping in the router and use navigation helpers from widgets.
Navigation Actions And State
Use context.go('/path') for replacing the current location and context.push('/path') to push a new entry onto the stack. Both methods keep code simple and readable compared to Navigator.push. Use named routes if you prefer symbolic names but path-based routes are more explicit for mobile and web.
You can also read the current location via GoRouter.of(context).location. For conditional navigation (for example, authentication), implement a redirect callback on the router constructor. Redirects run before building the target route and return a new location if navigation should be rerouted.
Example redirect pattern:
If the user is unauthenticated and tries to access a protected route, redirect to '/login'.
After sign-in, use context.go('/protected') to land on the intended page.
Go Router's state-driven model makes it straightforward to write unit tests that assert that certain inputs (URL, auth flags) produce expected redirections or pages.
Nested Navigation And Shell Routes
Real-world apps often need nested navigation: a bottom navigation bar with independent stacks or tabbed interfaces. Go Router supports nested routes and ShellRoute for shell-based layouts.
Use ShellRoute to provide a persistent parent widget (like BottomNavigationBar) while child routes swap content inside the shell. Each child can have its own nested route tree, preserving their stacks independently.
Key design notes:
Keep nested stacks shallow for clarity; deep nesting confuses back behavior.
Use shell routes when the parent UI must remain while children change.
Manage selected tab state via the URL so deep links open the correct tab and screen.
Example approach: a ShellRoute defines the scaffold with bottom navigation, and its subroutes map to tab content. Each tab's path appears in the URL so users can share links directly to a tab and a nested screen.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Go Router brings declarative, URL-first routing to Flutter mobile development. Centralize route definitions, prefer context.go/context.push for navigation, and use GoRouterState to read params and query data. For complex app shells and tabbed layouts, ShellRoute and nested routes give predictable stack behavior and deep-linking support. Implement redirects for auth flows and write straightforward tests against your router configuration to keep navigation robust and maintainable.
Introduction
Go Router is the recommended routing package for modern Flutter apps. It provides a declarative, URL-centered API that fits both mobile development and web targets. If you’re building a Flutter app that needs clean deep links, nested navigation, or predictable back-stack behavior, Go Router simplifies wiring routes into MaterialApp.router while making tests and state restoration easier.
Router Setup
Start by adding go_router to pubspec.yaml. Create a GoRouter instance and attach it to MaterialApp.router. Keep your routes centralized so navigation logic and URL structure are explicit.
final router = GoRouter(
routes: [
GoRoute(path: '/', builder: (c, s) => const HomePage()),
GoRoute(path: '/items/:id', builder: (c, s) => ItemPage(id: s.params['id']!)),
],
);
void main() => runApp(MaterialApp.router(routerConfig: router));This pattern replaces Navigator.push calls sprinkled across widgets. The router config controls parsing, redirection, and error handling in one place, improving maintainability for mobile development projects.
Declarative Routes And Parameters
Go Router is declarative: routes are defined as data, not as imperative push/pop calls. Path parameters and query parameters are available via the GoRouterState passed to route builders.
Access path parameters with state.params and query parameters with state.queryParams. Because builders receive state, UI can react directly to URL changes which is important for deep linking and testing.
Example: handling a route parameter and a search query.
GoRoute(
path: '/search/:category',
builder: (context, state) {
final category = state.params['category']!;
final q = state.queryParams['q'] ?? '';
return SearchPage(category: category, query: q);
},
),Avoid embedding navigation logic inside widgets. Keep route-to-widget mapping in the router and use navigation helpers from widgets.
Navigation Actions And State
Use context.go('/path') for replacing the current location and context.push('/path') to push a new entry onto the stack. Both methods keep code simple and readable compared to Navigator.push. Use named routes if you prefer symbolic names but path-based routes are more explicit for mobile and web.
You can also read the current location via GoRouter.of(context).location. For conditional navigation (for example, authentication), implement a redirect callback on the router constructor. Redirects run before building the target route and return a new location if navigation should be rerouted.
Example redirect pattern:
If the user is unauthenticated and tries to access a protected route, redirect to '/login'.
After sign-in, use context.go('/protected') to land on the intended page.
Go Router's state-driven model makes it straightforward to write unit tests that assert that certain inputs (URL, auth flags) produce expected redirections or pages.
Nested Navigation And Shell Routes
Real-world apps often need nested navigation: a bottom navigation bar with independent stacks or tabbed interfaces. Go Router supports nested routes and ShellRoute for shell-based layouts.
Use ShellRoute to provide a persistent parent widget (like BottomNavigationBar) while child routes swap content inside the shell. Each child can have its own nested route tree, preserving their stacks independently.
Key design notes:
Keep nested stacks shallow for clarity; deep nesting confuses back behavior.
Use shell routes when the parent UI must remain while children change.
Manage selected tab state via the URL so deep links open the correct tab and screen.
Example approach: a ShellRoute defines the scaffold with bottom navigation, and its subroutes map to tab content. Each tab's path appears in the URL so users can share links directly to a tab and a nested screen.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Go Router brings declarative, URL-first routing to Flutter mobile development. Centralize route definitions, prefer context.go/context.push for navigation, and use GoRouterState to read params and query data. For complex app shells and tabbed layouts, ShellRoute and nested routes give predictable stack behavior and deep-linking support. Implement redirects for auth flows and write straightforward tests against your router configuration to keep navigation robust and maintainable.
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.






















