Learn

Migrate from Navigator, go_router, or auto_route

Translate existing routes and stack behavior incrementally without rewriting feature UI in one release.

v1.1.0Intermediate

Migrate from Navigator, go_router, or auto_route

Migrate one flow at a time. First write down the behavior users rely on: URL, Back stack, replacement semantics, returned result, auth redirect, nested Navigator, and restoration.

Replace route arguments with Destinations

dart
// Before
context.push('/products/42', extra: product);

// After
context.readNavigation.push<void>(
  const ProductDestination(productId: '42'),
);

Move path and query encoding into the Route Definition. Feature code should not assemble URLs.

Translate operations, not method names

Existing intentArk Navigation
Navigator.push / context.pushpush
replacementreplaceTop
clear stack and open HomereplaceAll
pop to a named placepopUntil with a typed matcher
StatefulShellRoute / tabs routerchild Scopes + NavigationActiveOutlet
redirect callbackNavigationRedirect
access checkNavigationGuard

Do not translate go() mechanically. Decide whether the old call actually replaces the top, replaces the whole stack, or selects a branch, then use that exact operation.

Keep old and new flows temporarily

Mount the migrated flow under one shell or entry point. Old screens can open that entry through an adapter, and the migrated flow can return one typed result. Avoid running two routers over the same Navigator stack.

A safe order

  1. Introduce Destination types for one feature.
  2. Create Route Definitions and URI codecs.
  3. Build one Module and Mount.
  4. Replace calls inside that feature with NavigationPort.
  5. Verify Back, deep links, and auth behavior.
  6. Remove the old route definitions for that feature.

Use the first-route tutorial for the target shape and the modular-tabs tutorial before replacing a nested router.