GoRouter.dev

Current field guide · 2026

go, push, and the way back

Use go for a destination described by your route tree; use push when you deliberately want another page on the current stack.

Edition published 21 Oct 2026go_router 18.1.1 reference
On this page

Pick the user intention first

Changing a primary destination, opening a detail above the current screen, and replacing a transient screen are different actions. Choose an operation for the expected Back behavior, rather than selecting the shortest method name.

Destination navigation

context.go() navigates to the location and builds the corresponding route configuration. It is useful when the location itself should define the resulting page hierarchy. context.push() adds a location above the current stack and can return a result when that page is popped.

Browser history is a separate test

Do not assume imperative page pushes create the same web history as links or destination navigation. Test browser Back, Forward, a pasted link, and a fresh reload on the exact package version you ship. Extra data that exists only in memory is not a durable replacement for a URL.

Returning a result

Await the pushed route only when your flow really needs a result. After asynchronous work, check that the widget context is still mounted before using it. For navigation that should be discoverable as a real link, consider the Link widget from url_launcher alongside your route configuration.

dart / example
// Change the destination.
context.go('/books/42');

// Open another page and await its result.
final saved = await context.push<bool>('/books/42/edit');
if (!context.mounted) return;

// From the editor:
context.pop(true);
Earlier edition: read the complete original guide. Its older APIs are kept in historical context.

Sources & version context

GoRouter.dev documentation edition. Examples illustrate the APIs described in the linked primary documentation. Adapt application-owned widgets and services to your project. They are not an executed Flutter session in this browser.

Run a real stack test: go replaces the location; push adds a page

The difference is observable in the existing starter, rather than inferred from the JavaScript Route Atlas model. This example pins go_router 18.1.1 with the already available Flutter SDK. It tests the widget navigation stack, not the browser’s Back/Forward implementation.

  1. Use the starter linked on Getting started. Keep its lockfile. Add the complete test below as test/navigation_stack_test.dart; it is an additional test, not a claim that the older ZIP already contains this file.
  2. Run flutter analyze --no-pub and flutter test --no-pub --reporter expanded after resolving the pinned dependencies.
  3. Run flutter build web --release --csp --no-web-resources-cdn --no-wasm-dry-run --no-pub. Check navigation in the resulting application separately before relying on browser history behaviour.

Observed on 28 October 2026: analysis found no issues; all five tests passed, including the added stack test; the release Web build completed. The test goes directly to Book 42 with the notes tab and observes canPop == false. Starting from Home and pushing that same location observes canPop == true; pop returns Home without an exception.

Complete executed test
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gorouter_starter/main.dart';

void main() {
  testWidgets('go selects a top-level stack; push retains Home', (
    tester,
  ) async {
    final router = createRouter();
    addTearDown(router.dispose);
    await tester.pumpWidget(MaterialApp.router(routerConfig: router));
    await tester.pumpAndSettle();
    router.go('/books/42?tab=notes');
    await tester.pumpAndSettle();
    expect(find.text('Book 42'), findsOneWidget);
    expect(find.text('Tab: notes'), findsOneWidget);
    expect(router.canPop(), isFalse);
    router.go('/');
    await tester.pumpAndSettle();
    router.push('/books/42?tab=notes');
    await tester.pumpAndSettle();
    expect(find.text('Book 42'), findsOneWidget);
    expect(router.canPop(), isTrue);
    router.pop();
    await tester.pumpAndSettle();
    expect(find.text('GoRouter starter'), findsOneWidget);
    expect(tester.takeException(), isNull);
  });
}

These results establish the tested starter’s stack and compilation on the recorded SDK. They do not prove every navigation pattern, an unpinned future version, or real browser Back/Forward across external pages. Keep the distinction between route matching, widget stack and browser history in your own regression record.

Run a real stack test: go replaces the location; push adds a page
go: [Book 42] · push: [Home, Book 42] · pop: [Home].

Source: pub.dev.

Find your next route