[go_router] Add documentation using dartdoc topics (#2789)

* Add documentation using dartdoc topics

* Remove custom analysis options for example code

* Address code review comments

* Add nested navigation documentation, remove empty nested.md file.

* remove accidentally-committed file

* Update changelog

* Update pubspec

* Address code review comments

* Update pubspec.yaml

* Fix gorouter.dev link

fixes flutter/flutter#115078

* inconsistent periods
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index 146368b..7653429 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 5.1.7
+
+- Adds documentation using dartdoc topics
+
 ## 5.1.6
 
 - Fixes crashes when multiple `GoRoute`s use the same `parentNavigatorKey` in a route subtree.
diff --git a/packages/go_router/README.md b/packages/go_router/README.md
index 020039e..c2a9b10 100644
--- a/packages/go_router/README.md
+++ b/packages/go_router/README.md
@@ -1,235 +1,55 @@
 # go_router
-
-A Declarative Routing Package for Flutter.
-
-This package uses the Flutter framework's Router API to provide a
+A declarative routing package for Flutter that uses the Router API to provide a
 convenient, url-based API for navigating between different screens. You can
-define URL patterns, navigate using a URL, handle deep links,
-and a number of other navigation-related scenarios.
+define URL patterns, navigate using a URL, handle deep links, and a number of
+other navigation-related scenarios.
 
-## Getting Started
+## Features
+GoRouter has a number of features to make navigation straightforward:
 
-Follow the [package install instructions](https://pub.dev/packages/go_router/install),
-and you can start using go_router in your app:
+- Parsing path and query parameters using a template syntax (for example, "user/:id')
+- Displaying multiple screens for a destination (sub-routes)
+- Redirection support - you can re-route the user to a different URL based on
+  application state, for example to a sign-in when the user is not
+  authenticated
+- Support for multiple Navigators via
+  [ShellRoute](https://pub.dev/documentation/go_router/ShellRoute-class.html) -
+  you can display an inner Navigator that displays its own pages based on the
+  matched route. For example, to display a BottomNavigationBar that stays
+  visible at the bottom of the
+  screen
+- Support for both Material and Cupertino apps
+- Backwards-compatibility with Navigator API
 
-```dart
-import 'package:flutter/material.dart';
-import 'package:go_router/go_router.dart';
+## Documentation
+See the API documentation for details on the following topics:
 
-void main() => runApp(App());
-
-class App extends StatelessWidget {
-  App({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return MaterialApp.router(
-      routerConfig: _router,
-      title: 'GoRouter Example',
-    );
-  }
-
-  final GoRouter _router = GoRouter(
-    routes: <GoRoute>[
-      GoRoute(
-        path: '/',
-        builder: (BuildContext context, GoRouterState state) {
-          return ScreenA();
-        },
-      ),
-      GoRoute(
-        path: '/b',
-        builder: (BuildContext context, GoRouterState state) {
-          return ScreenB();
-        },
-      ),
-    ],
-  );
-}
-```
-
-## Define Routes
-
-go_router is governed by a set of routes which are specified as part of the
-[GoRouter](https://pub.dev/documentation/go_router/latest/go_router/GoRouter-class.html)
-constructor:
-
-```dart
-GoRouter(
-  routes: [
-    GoRoute(
-      path: '/',
-      builder: (context, state) => const Page1Screen(),
-    ),
-    GoRoute(
-      path: '/page2',
-      builder: (context, state) => const Page2Screen(),
-    ),
-  ],
-);
-```
-
-In the above snippet, two routes are defined, `/` and `/page2`.
-When the URL changes, it is matched against each route path.
-The path is matched in a case-insensitive way, but the case for 
-parameters is preserved. If there are multiple route matches, 
-the **first match** in the list takes priority over the others.
-
-The [builder](https://pub.dev/documentation/go_router/latest/go_router/GoRoute/builder.html)
-is responsible for building the `Widget` to display on screen.
-Alternatively, you can use `pageBuilder` to customize the transition 
-animation when that route becomes active.
-The default transition is used between pages
-depending on the app at the top of its widget tree, e.g. the use of `MaterialApp`
-will cause go_router to use the `MaterialPage` transitions. Consider using
-[pageBuilder](https://pub.dev/documentation/go_router/latest/go_router/GoRoute/pageBuilder.html)
-for custom `Page` class.
-
-## Initialization
-
-Create a [GoRouter](https://pub.dev/documentation/go_router/latest/go_router/GoRouter-class.html)
-object and initialize your `MaterialApp` or `CupertinoApp`:
-
-```dart
-final GoRouter _router = GoRouter(
-  routes: <GoRoute>[
-     // ...
-  ]
-);
-
-MaterialApp.router(
-  routerConfig: _router,
-);
-```
-
-## Error handling
-
-By default, go_router comes with default error screens for both `MaterialApp` and
-`CupertinoApp` as well as a default error screen in the case that none is used.
-Once can also replace the default error screen by using the [errorBuilder](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/GoRouter.html):
-
-```dart
-GoRouter(
-  ...
-  errorBuilder: (context, state) => ErrorScreen(state.error),
-);
-```
-
-## Redirection
-
-You can use redirection to prevent the user from visiting a specific page. In
-go_router, redirection can be asynchronous.
-
-```dart
-GoRouter(
-  ...
-  redirect: (context, state) async {
-    if (await LoginService.of(context).isLoggedIn) {
-      // No redirect is required if the user is already logged in.
-      return null;
-    }
-    return '/login';
-  },
-);
-```
-
-If the code depends on [BuildContext](https://api.flutter.dev/flutter/widgets/BuildContext-class.html)
-through the [dependOnInheritedWidgetOfExactType](https://api.flutter.dev/flutter/widgets/BuildContext/dependOnInheritedWidgetOfExactType.html)
-(which is how `of` methods are usually implemented), the redirect will be called every time the [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html)
-updated.
-
-### Top-level redirect
-
-The [GoRouter.redirect](https://pub.dev/documentation/go_router/latest/go_router/GoRouter-class.html)
-is always called for every navigation regardless of which GoRoute was matched. The
-top-level redirect always takes priority over route-level redirect.
-
-### Route-level redirect
-
-If the top-level redirect does not redirect to a different location,
-the [GoRoute.redirect](https://pub.dev/documentation/go_router/latest/go_router/GoRoute/redirect.html)
-is then called if the route has matched the GoRoute. If there are multiple
-GoRoute matches, e.g. GoRoute with sub-routes, the parent route redirect takes
-priority over sub-routes' redirect.
-
-## Navigation
-
-To navigate between routes, use the [GoRouter.go](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/go.html) method:
-
-```dart
-onTap: () => GoRouter.of(context).go('/page2')
-```
-
-go_router also provides a more concise way to navigate using Dart extension
-methods:
-
-```dart
-onTap: () => context.go('/page2')
-```
-
-## Nested Navigation
-
-The `ShellRoute` route type provides a way to wrap all sub-routes with a UI shell.
-Under the hood, GoRouter places a Navigator in the widget tree, which is used
-to display matching sub-routes:
-
-```dart
-final  _router = GoRouter(
-  routes: [
-    ShellRoute(
-      builder: (context, state, child) {
-        return AppScaffold(child: child);
-      },
-      routes: <RouteBase>[
-        GoRoute(
-          path: '/albums',
-          builder: (context, state) {
-            return HomeScreen();
-          },
-          routes: <RouteBase>[
-            /// The details screen to display stacked on the inner Navigator.
-            GoRoute(
-              path: 'song/:songId',
-              builder: (BuildContext context, GoRouterState state) {
-                return const DetailsScreen(label: 'A');
-              },
-            ),
-          ],
-        ),
-      ],
-    ),
-  ],
-);
-```
-
-For more details, see the
-[ShellRoute](https://pub.dev/documentation/go_router/latest/go_router/ShellRoute-class.html)
-API documentation. For a complete
-example, see the 
-[ShellRoute sample](https://github.com/flutter/packages/tree/main/packages/go_router/example/lib/shell_route.dart)
-in the example/ directory.
-
-### Still not sure how to proceed?
-See [examples](https://github.com/flutter/packages/tree/main/packages/go_router/example) for complete runnable examples or visit [API documentation](https://pub.dev/documentation/go_router/latest/go_router/go_router-library.html)
-
+- [Getting started](https://pub.dev/documentation/go_router/latest/topics/Get%20started-topic.html)
+- [Upgrade an existing app](https://pub.dev/documentation/go_router/latest/topics/Upgrading-topic.html)
+- [Configuration](https://pub.dev/documentation/go_router/latest/topics/Configuration-topic.html)
+- [Navigation](https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html)
+- [Redirection](https://pub.dev/documentation/go_router/latest/topics/Redirection-topic.html)
+- [Web](https://pub.dev/documentation/go_router/latest/topics/Web-topic.html)
+- [Deep linking](https://pub.dev/documentation/go_router/latest/topics/Deep%20linking-topic.html)
+- [Transition animations](https://pub.dev/documentation/go_router/latest/topics/Transition%20animations-topic.html)
+- [Type-safe routes](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html)
+- [Named routes](https://pub.dev/documentation/go_router/latest/topics/Named%20routes-topic.html)
+- [Logging](https://pub.dev/documentation/go_router/latest/topics/Logging-topic.html)
+- [Error handling](https://pub.dev/documentation/go_router/latest/topics/Error%20handling-topic.html)
 
 ## Migration guides
-
-- [Migrating to 2.0](https://flutter.dev/go/go-router-v2-breaking-changes)
-- [Migrating to 2.5](https://flutter.dev/go/go-router-v2-5-breaking-changes)
-- [Migrating to 3.0](https://flutter.dev/go/go-router-v3-breaking-changes)
-- [Migrating to 4.0](https://flutter.dev/go/go-router-v4-breaking-changes)
-- [Migrating to 5.0](https://flutter.dev/go/go-router-v5-breaking-changes)
 - [Migrating to 5.1.2](https://flutter.dev/go/go-router-v5-1-2-breaking-changes)
+- [Migrating to 5.0](https://flutter.dev/go/go-router-v5-breaking-changes)
+- [Migrating to 4.0](https://flutter.dev/go/go-router-v4-breaking-changes)
+- [Migrating to 3.0](https://flutter.dev/go/go-router-v3-breaking-changes)
+- [Migrating to 2.5](https://flutter.dev/go/go-router-v2-5-breaking-changes)
+- [Migrating to 2.0](https://flutter.dev/go/go-router-v2-breaking-changes)
 
 ## Changelog
-
-See the [Changelog](https://github.com/flutter/packages/blob/main/packages/go_router/CHANGELOG.md)
+See the
+[Changelog](https://github.com/flutter/packages/blob/main/packages/go_router/CHANGELOG.md)
 for a list of new features and breaking changes.
 
 ## Roadmap
-
-See the [github project](https://github.com/orgs/flutter/projects/17/) for our current priority.
-
-
-
+See the [GitHub project](https://github.com/orgs/flutter/projects/17/) for a 
+prioritized list of feature requests and known issues.
diff --git a/packages/go_router/dartdoc_options.yaml b/packages/go_router/dartdoc_options.yaml
new file mode 100644
index 0000000..6759a53
--- /dev/null
+++ b/packages/go_router/dartdoc_options.yaml
@@ -0,0 +1,51 @@
+dartdoc:
+  categories:
+    "Get started":
+      markdown: doc/get-started.md
+      name: Get started
+    "Upgrading":
+      markdown: doc/upgrading.md
+      name: Upgrade an existing app
+    "Configuration":
+      markdown: doc/configuration.md
+      name: Configuration
+    "Navigation":
+      markdown: doc/navigation.md
+      name: Navigation
+    "Redirection":
+      markdown: doc/redirection.md
+      name: Redirection
+    "Web":
+      markdown: doc/web.md
+      name: Web
+    "Deep linking":
+      markdown: doc/deep-linking.md
+      name: Deep linking
+    "Transition animations":
+      markdown: doc/transition-animations.md
+      name: Transition animations
+    "Type-safe routes":
+      markdown: doc/type-safe-routes.md
+      name: Type-safe routes
+    "Named routes":
+      markdown: doc/named-routes.md
+      name: Type-safe routes
+    "Error handling":
+      markdown: doc/error-handling.md
+      name: Error handling
+  categoryOrder:
+    - "Get started"
+    - "Upgrading"
+    - "Configuration"
+    - "Navigation"
+    - "Redirection"
+    - "Web"
+    - "Deep linking"
+    - "Transition animations"
+    - "Type-safe routes"
+    - "Named routes"
+    - "Error handling"
+  showUndocumentedCategories: true
+  ignore:
+    - broken-link
+    - missing-from-search-index
diff --git a/packages/go_router/doc/configuration.md b/packages/go_router/doc/configuration.md
new file mode 100644
index 0000000..edd19d1
--- /dev/null
+++ b/packages/go_router/doc/configuration.md
@@ -0,0 +1,155 @@
+Create a GoRouter configuration by calling the [GoRouter][] constructor and
+providing list of [GoRoute][] objects:
+
+```dart
+GoRouter(
+  routes: [
+    GoRoute(
+      path: '/',
+      builder: (context, state) => const Page1Screen(),
+    ),
+    GoRoute(
+      path: '/page2',
+      builder: (context, state) => const Page2Screen(),
+    ),
+  ],
+);
+```
+
+# GoRoute
+To configure a GoRoute, a path template and builder must be provided. Specify a
+path template to handle by providing a `path` parameter, and a builder by
+providing either the `builder` or `pageBuilder` parameter:
+
+```dart
+GoRoute(
+  path: '/users/:userId',
+  builder: (context, state) => const UserScreen(),
+),
+```
+
+To navigate to this route, use
+[go()](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/go.html).
+To learn more about how navigation, visit the
+[Navigation](https://pub.dev/documentation/go_router/topics/Configuration-topic.html)
+topic.
+
+# Parameters
+To specify a path parameter, prefix a path segment with a `:` character,
+followed by a unique name, for example, `:userId`. You can access the value of
+the parameter by accessing it through the [GoRouterState][] object provided to
+the builder callback:
+
+```dart
+GoRoute(
+  path: '/users/:userId',
+  builder: (context, state) => const UserScreen(id: state.params['userId']),
+),
+```
+
+Similarly, to access a [query
+string](https://en.wikipedia.org/wiki/Query_string) parameter (the part of URL
+after the `?`), use [GoRouterState][]. For example, a URL path such as
+`/users?filter=admins` can read the `filter` parameter:
+
+```dart
+GoRoute(
+  path: '/users',
+  builder: (context, state) => const UsersScreen(filter: state.queryParams['filter']),
+),
+```
+
+# Child routes
+A matched route can result in more than one screen being displayed on a
+Navigator. This is equivalent to calling `push()`, where a new screen is
+displayed above the previous screen with a transition animation, and with an
+in-app back button in the `AppBar` widget, if it is used.
+
+To display a screen on top of another, add a child route by adding it to the
+parent route's `routes` list:
+
+```dart
+GoRoute(
+  path: '/',
+  builder: (context, state) {
+    return HomeScreen();
+  },
+  routes: [
+    GoRoute(
+      path: 'details',
+      builder: (context, state) {
+        return DetailsScreen();
+      },
+    ),
+  ],
+)
+```
+
+# Nested navigation
+Some apps display destinations in a subsection of the screen, for example, an
+app using a BottomNavigationBar that stays on-screen when navigating between
+destinations.
+
+To add an additional Navigator, use
+[ShellRoute](https://pub.dev/documentation/go_router/ShellRoute-class.html)
+and provide a builder that returns a widget:
+
+```dart
+ShellRoute(
+  builder:
+      (BuildContext context, GoRouterState state, Widget child) {
+    return Scaffold(
+      body: child,
+      /* ... */
+      bottomNavigationBar: BottomNavigationBar(
+      /* ... */
+      ),
+    );
+  },
+  routes: <RouteBase>[
+    GoRoute(
+      path: 'details',
+      builder: (BuildContext context, GoRouterState state) {
+        return const DetailsScreen();
+      },
+    ),
+  ],
+),
+```
+
+The `child` widget is a Navigator configured to display the matching sub-routes.
+
+For more details, see the [ShellRoute API
+documentation](https://pub.dev/documentation/go_router/latest/go_router/ShellRoute-class.html).
+For a complete example, see the [ShellRoute
+sample](https://github.com/flutter/packages/tree/main/packages/go_router/example/lib/shell_route.dart)
+in the example/ directory.
+
+# Initial location
+
+The initial location is shown when the app first opens and there is no deep link
+provided by the platform. To specify the initial location, provide the
+`initialLocation` parameter to the
+GoRouter constructor:
+
+```dart
+GoRouter(
+  initialLocation: '/details',
+  /* ... */
+);
+```
+
+# Logging
+
+To enable log output, enable the `debugLogDiagnostics` parameter:
+
+```dart
+final _router = GoRouter(
+  routes: [/* ... */],
+  debugLogDiagnostics: true,
+);
+```
+
+[GoRouter]: https://pub.dev/documentation/go_router/latest/go_router/GoRouter-class.html
+[GoRoute]: https://pub.dev/documentation/go_router/latest/go_router/GoRoute-class.html
+[GoRouterState]: https://pub.dev/documentation/go_router/latest/go_router/GoRouterState-class.html
\ No newline at end of file
diff --git a/packages/go_router/doc/deep-linking.md b/packages/go_router/doc/deep-linking.md
new file mode 100644
index 0000000..29b198a
--- /dev/null
+++ b/packages/go_router/doc/deep-linking.md
@@ -0,0 +1,5 @@
+When a deep link is received from the platform, GoRouter will display the
+configured screen based on the URL path. To configure your Android or iOS app
+for deep linking, see the [Deep
+linking](https://docs.flutter.dev/development/ui/navigation/deep-linking)
+documentation at flutter.dev.
\ No newline at end of file
diff --git a/packages/go_router/doc/error-handling.md b/packages/go_router/doc/error-handling.md
new file mode 100644
index 0000000..1021189
--- /dev/null
+++ b/packages/go_router/doc/error-handling.md
@@ -0,0 +1,12 @@
+By default, go_router comes with default error screens for both `MaterialApp`
+and `CupertinoApp` as well as a default error screen in the case that none is
+used. You can also replace the default error screen by using the
+[errorBuilder](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/GoRouter.html)
+parameter:
+
+```dart
+GoRouter(
+  /* ... */
+  errorBuilder: (context, state) => ErrorScreen(state.error),
+);
+```
diff --git a/packages/go_router/doc/get-started.md b/packages/go_router/doc/get-started.md
new file mode 100644
index 0000000..9ea5ff9
--- /dev/null
+++ b/packages/go_router/doc/get-started.md
@@ -0,0 +1,38 @@
+To get started, follow the [package installation
+instructions](https://pub.dev/packages/go_router/install) and add a GoRouter
+configuration to your app:
+
+```dart
+import 'package:go_router/go_router.dart';
+
+// GoRouter configuration
+final _router = GoRouter(
+  routes: [
+    GoRoute(
+      path: '/',
+      builder: (context, state) => HomeScreen(),
+    ),
+  ],
+);
+```
+
+To use this configuration in your app, use either the `MaterialApp.router` or
+`CupertinoApp.router` constructor and set the `routerConfig` parameter to your
+GoRouter configuration object:
+
+```
+class MyApp extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp.router(
+      routerConfig: _router,
+    );
+  }
+}
+```
+
+For a complete sample, see the [Getting started sample][] in the example directory.
+For more on how to configure GoRouter, see [Configuration].
+
+[Getting started sample]: https://github.com/flutter/packages/tree/main/packages/go_router/example/lib/main.dart
+[Configuration]: https://pub.dev/documentation/go_router/topics/Configuration-topic.html 
diff --git a/packages/go_router/doc/named-routes.md b/packages/go_router/doc/named-routes.md
new file mode 100644
index 0000000..54705d1
--- /dev/null
+++ b/packages/go_router/doc/named-routes.md
@@ -0,0 +1,53 @@
+Instead of navigating to a route based on the URL, a GoRoute can be given a unique
+name. To configure a named route, use the `name` parameter:
+
+```dart
+GoRoute(
+   name: 'song',
+   path: 'songs/:songId',
+   builder: /* ... */,
+ ),
+```
+
+To navigate to a route using its name, call [`goNamed`](https://pub.dev/documentation/go_router/latest/go_router/GoRouter/goNamed.html):
+
+```dart
+TextButton(
+  onPressed: () {
+    context.goNamed('song', params: {'songId': 123});
+  },
+  child: const Text('Go to song 2'),
+),
+```
+
+Alternatively, you can look up the location for a name using `namedLocation`:
+
+```dart
+TextButton(
+  onPressed: () {
+    final String location = context.namedLocation('song', params: {'songId': 123});
+    context.go(location);
+  },
+  child: const Text('Go to song 2'),
+),
+```
+
+To learn more about navigation, see the [Navigation][] topic.
+
+## Redirecting to a named route
+To redirect to a named route, use the `namedLocation` API:
+
+```dart
+redirect: (BuildContext context, GoRouterState state) {
+  if (AuthState.of(context).isSignedIn) {
+    return context.namedLocation('signIn');
+  } else {
+    return null;
+  }   
+},
+```
+
+To learn more about redirection, see the [Redirection][] topic.
+
+[Navigation]: https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html
+[Redirection]: https://pub.dev/documentation/go_router/latest/topics/Redirection-topic.html
diff --git a/packages/go_router/doc/navigation.md b/packages/go_router/doc/navigation.md
new file mode 100644
index 0000000..93d51ed
--- /dev/null
+++ b/packages/go_router/doc/navigation.md
@@ -0,0 +1,71 @@
+There are many ways to navigate between destinations in your app.
+
+## Go directly to a destination
+Navigating to a destination in GoRouter will replace the current stack of screens with the screens configured to be displayed
+for the destination route. To change to a new screen, call `context.go()` with a URL:
+
+```
+build(BuildContext context) {
+  return TextButton(
+    onPressed: () => context.go('/users/123'),
+  );
+}
+```
+
+This is shorthand for calling `GoRouter.of(context).go('/users/123)`.
+
+To build a URI with query parameters, you can use the `Uri` class from the Dart standard library:
+
+```
+context.go(Uri(path: '/users/123', queryParameters: {'filter': 'abc'}).toString());
+```
+
+## Imperative navigation
+GoRouter can push a screen onto the Navigator's history
+stack using `context.push()`, and can pop the current screen via
+`context.pop()`. However, imperative navigation is known to cause issues with
+the browser history.
+
+To learn more, see [issue
+#99112](https://github.com/flutter/flutter/issues/99112).
+
+## Using the Link widget
+You can use a Link widget from the url_launcher package to create a link to destinations in
+your app. This is equivalent to calling `context.go()`, but renders a real link
+on the web.
+
+To add a Link to your app, follow the [Link API
+documentation](https://pub.dev/documentation/url_launcher/latest/link/Link-class.html)
+from the url_launcher package.
+
+## Using named routes
+You can also use [Named routes] to navigate instead of using URLs.
+
+## Prevent navigation
+GoRouter and other Router-based APIs are not compatible with the
+[WillPopScope](https://api.flutter.dev/flutter/widgets/WillPopScope-class.html)
+widget.
+
+See [issue #102408](https://github.com/flutter/flutter/issues/102408)
+for details on what such an API might look like in go_router.
+
+## Imperative navigation with Navigator
+You can continue using the Navigator to push and pop pages. Pages displayed in
+this way are not deep-linkable and will be replaced if any parent page that is
+associated with a GoRoute is removed, for example when a new call to `go()`
+occurs.
+
+To push a screen using the imperative Navigator API, call
+[`NavigatorState.push()`](https://api.flutter.dev/flutter/widgets/NavigatorState/push.html):
+
+```dart
+Navigator.of(context).push(
+  MaterialPageRoute(
+    builder: (BuildContext context) {
+      return const DetailsScreen();
+    },
+  ),
+);
+```
+
+[Named routes]: https://pub.dev/documentation/go_router/latest/topics/Named%20routes-topic.html
diff --git a/packages/go_router/doc/redirection.md b/packages/go_router/doc/redirection.md
new file mode 100644
index 0000000..218fe60
--- /dev/null
+++ b/packages/go_router/doc/redirection.md
@@ -0,0 +1,42 @@
+Redirection changes the location to a new one based on application state. For
+example, redirection can be used to display a sign-in screen if the user is not
+logged in.
+
+A redirect is a callback of the type
+[GoRouterRedirect](go_router/GoRouterRedirect.html). To change incoming location
+based on some application state, add a callback to either the GoRouter or
+GoRoute constructor:
+
+
+```dart
+redirect: (BuildContext context, GoRouterState state) {
+  if (AuthState.of(context).isSignedIn) {
+    return '/signin';
+  } else {
+    return null;
+  }   
+},
+```
+
+To display the intended route without redirecting, return `null` or the original
+route path.
+
+## Top-level vs route-level redirection
+There are two types of redirection:
+
+- Top-level redirection: Defined on the `GoRouter` constructor. Called before
+  any navigation event.
+- Route-level redirection: Defined on the `GoRoute`
+  constructor. Called when a navigation event is about to display the route.
+
+## Named routes
+You can also redirect using [Named routes].
+
+## Considerations
+- You can specify a `redirectLimit` to configure the maximum number of redirects
+  that are expected to occur in your app. By default, this value is set to 5.
+  GoRouter will display the error screen if this redirect limit is exceeded (See
+  the [Error handling][] topic for more information on the error screen.)
+
+[Named routes]: https://pub.dev/documentation/go_router/latest/topics/Named%20routes-topic.html
+[Error handling]: https://pub.dev/documentation/go_router/topics/Error%20handling-topic.html
diff --git a/packages/go_router/doc/transition-animations.md b/packages/go_router/doc/transition-animations.md
new file mode 100644
index 0000000..a9a5901
--- /dev/null
+++ b/packages/go_router/doc/transition-animations.md
@@ -0,0 +1,31 @@
+GoRouter allows you to customize the transition animation for each GoRoute. To
+configure a custom transition animation, provide a `pageBuilder` parameter
+to the GoRoute constructor:
+
+```dart
+GoRoute(
+  path: 'details',
+  pageBuilder: (context, state) {
+    return CustomTransitionPage(
+      key: state.pageKey,
+      child: DetailsScreen(),
+      transitionsBuilder: (context, animation, secondaryAnimation, child) {
+        // Change the opacity of the screen using a Curve based on the the animation's
+        // value
+        return FadeTransition(
+          opacity:
+              CurveTween(curve: Curves.easeInOutCirc).animate(animation),
+          child: child,
+        );
+      },
+    );
+  },
+),
+```
+
+For a complete example, see the [transition animations
+sample](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/transition_animations.dart).
+
+For more information on animations in Flutter, visit the
+[Animations](https://docs.flutter.dev/development/ui/animations) page on
+flutter.dev.
\ No newline at end of file
diff --git a/packages/go_router/doc/type-safe-routes.md b/packages/go_router/doc/type-safe-routes.md
new file mode 100644
index 0000000..194e543
--- /dev/null
+++ b/packages/go_router/doc/type-safe-routes.md
@@ -0,0 +1,77 @@
+Instead of using URL strings to navigate, go_router supports
+type-safe routes using the go_router_builder package. 
+
+To get started, add [go_router_builder][], [build_runner][], and
+[build_verify][] to the dev_dependencies section of your pubspec.yaml:
+
+```yaml
+dev_dependencies:
+  go_router_builder: any
+  build_runner: any
+  build_verify: any
+```
+
+Then extend the [GoRouteData](https://pub.dev/documentation/go_router/latest/go_router/GoRouteData-class.html) class for each route in your app and add the
+TypedGoRoute annotation:
+
+```dart
+import 'package:go_router/go_router.dart';
+
+part 'go_router_builder.g.dart';
+
+@TypedGoRoute<HomeScreenRoute>(
+    path: '/',
+    routes: [
+      TypedGoRoute<SongRoute>(
+        path: 'song/:id',
+      )
+    ]
+)
+@immutable
+class HomeScreenRoute extends GoRouteData {
+  @override
+  Widget build(BuildContext context) {
+    return const HomeScreen();
+  }
+}
+
+@immutable
+class SongRoute extends GoRouteData {
+  final int id;
+
+  const SongRoute({
+    required this.id,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return SongScreen(songId: id.toString());
+  }
+}
+```
+
+To build the generated files (ending in .g.dart), use the build_runner command:
+
+```
+flutter pub global activate build_runner
+flutter pub run build_runner build
+```
+
+To navigate, construct a GoRouteData object with the required parameters and
+call go():
+
+```
+TextButton(
+  onPressed: () {
+    const SongRoute(id: 2).go(context);
+  },
+  child: const Text('Go to song 2'),
+),
+```
+
+For more information, visit the [go_router_builder
+package documentation](https://pub.dev/documentation/go_router_builder/latest/).
+
+[go_router_builder]: https://pub.dev/packages/go_router_builder
+[build_runner]: https://pub.dev/packages/build_runner
+[build_verify]: https://pub.dev/packages/build_verify
\ No newline at end of file
diff --git a/packages/go_router/doc/upgrading.md b/packages/go_router/doc/upgrading.md
new file mode 100644
index 0000000..72af6b9
--- /dev/null
+++ b/packages/go_router/doc/upgrading.md
@@ -0,0 +1,72 @@
+You can upgrade an existing app to go_router gradually, by starting with the
+home screen and creating a GoRoute for each screen you would like to be
+deep-linkable.
+
+# Upgrade an app that uses Navigator
+To upgrade an app that is already using the Navigator for routing, start with
+a single route for the home screen:
+
+```dart
+import 'package:go_router/go_router.dart';
+
+final _router = GoRouter(
+  routes: [
+    GoRoute(
+      path: '/',
+      builder: (context, state) => const HomeScreen(),
+    ),
+  ],
+);
+
+class MyApp extends StatelessWidget {
+  const MyApp({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp.router(
+      routerConfig: _router,
+    );
+  }
+}
+```
+
+GoRouter leverages the Router API to provide backward compatibility with the
+Navigator, so any calls to `Navigator.of(context).push()` or
+`Navigator.of(context).pop()` will continue to work, but these destinations
+aren't deep-linkable. You can gradually add more routes to the GoRouter
+configuration.
+
+# Upgrade an app that uses named routes
+An app that uses named routes can be migrated to go_router by changing each
+entry in the map to a GoRoute object and changing any calls to
+`Navigator.of(context).pushNamed` to `context.go()`.
+
+For example, if you are starting with an app like this:
+
+```dart
+MaterialApp(
+  initialRoute: '/details',
+  routes: {
+    '/': (context) => HomeScreen(),
+    '/details': (context) => DetailsScreen(),
+  },
+);
+```
+
+Then the GoRouter configuration would look like this:
+
+```dart
+GoRouter(
+  initialRoute: '/details',
+  routes: [
+    GoRoute(
+      path: '/',
+      builder: (context, state) => const HomeScreen(),
+    ),
+    GoRoute(
+      path: '/details',
+      builder: (context, state) => const DetailsScreen(),
+    ),
+  ],
+);
+```
diff --git a/packages/go_router/doc/web.md b/packages/go_router/doc/web.md
new file mode 100644
index 0000000..1f9b272
--- /dev/null
+++ b/packages/go_router/doc/web.md
@@ -0,0 +1,4 @@
+Flutter apps can use the hash fragment or URL path for navigation. To learn more
+about how to configure your app, visit the [URL strategy on the
+web](https://docs.flutter.dev/development/ui/navigation/url-strategies) page on
+flutter.dev.
\ No newline at end of file
diff --git a/packages/go_router/example/README.md b/packages/go_router/example/README.md
index d6ffa67..90c7aad 100644
--- a/packages/go_router/example/README.md
+++ b/packages/go_router/example/README.md
@@ -1,9 +1,9 @@
 # Example Catalog
 
-## [Routes](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/main.dart)
+## [Get started](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/main.dart)
 `flutter run lib/main.dart`
 
-An example to demonstrate a simple two-pages app.
+An example to demonstrate a simple two-page app.
 
 ## [Sub-routes](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/sub_routes.dart)
 `flutter run lib/sub_routes.dart`
diff --git a/packages/go_router/example/lib/main.dart b/packages/go_router/example/lib/main.dart
index c47fc49..3b513df 100644
--- a/packages/go_router/example/lib/main.dart
+++ b/packages/go_router/example/lib/main.dart
@@ -5,89 +5,93 @@
 import 'package:flutter/material.dart';
 import 'package:go_router/go_router.dart';
 
-// This scenario demonstrates a simple two-page app.
-//
-// The first route '/' is mapped to Page1Screen, and the second route '/page2'
-// is mapped to Page2Screen. To navigate between pages, press the buttons on the
-// pages.
-//
-// The onPress callbacks use context.go() to navigate to another page. This is
-// equivalent to entering url to the browser url bar directly.
+/// This sample app shows an app with two screens.
+///
+/// The first route '/' is mapped to [HomeScreen], and the second route
+/// '/details' is mapped to [DetailsScreen].
+///
+/// The buttons use context.go() to navigate to each destination. On mobile
+/// devices, each destination is deep-linkable and on the web, can be navigated
+/// to using the address bar.
+void main() => runApp(const MyApp());
 
-void main() => runApp(App());
+/// The route configuration.
+final GoRouter _router = GoRouter(
+  routes: <RouteBase>[
+    GoRoute(
+      path: '/',
+      builder: (BuildContext context, GoRouterState state) {
+        return const HomeScreen();
+      },
+      routes: <RouteBase>[
+        GoRoute(
+          path: 'details',
+          builder: (BuildContext context, GoRouterState state) {
+            return const DetailsScreen();
+          },
+        ),
+      ],
+    ),
+  ],
+);
 
 /// The main app.
-class App extends StatelessWidget {
-  /// Creates an [App].
-  App({Key? key}) : super(key: key);
-
-  /// The title of the app.
-  static const String title = 'GoRouter Example: Declarative Routes';
+class MyApp extends StatelessWidget {
+  /// Constructs a [MyApp]
+  const MyApp({Key? key}) : super(key: key);
 
   @override
-  Widget build(BuildContext context) => MaterialApp.router(
-        routerConfig: _router,
-        title: title,
-      );
+  Widget build(BuildContext context) {
+    return MaterialApp.router(
+      routerConfig: _router,
+    );
+  }
+}
 
-  final GoRouter _router = GoRouter(
-    routes: <GoRoute>[
-      GoRoute(
-        path: '/',
-        builder: (BuildContext context, GoRouterState state) =>
-            const Page1Screen(),
-        routes: <GoRoute>[
-          GoRoute(
-            path: 'page2',
-            builder: (BuildContext context, GoRouterState state) =>
-                const Page2Screen(),
-          ),
-        ],
+/// The home screen
+class HomeScreen extends StatelessWidget {
+  /// Constructs a [HomeScreen]
+  const HomeScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(title: const Text('Home Screen')),
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            ElevatedButton(
+              onPressed: () => context.go('/details'),
+              child: const Text('Go to the Details screen'),
+            ),
+          ],
+        ),
       ),
-    ],
-  );
+    );
+  }
 }
 
-/// The screen of the first page.
-class Page1Screen extends StatelessWidget {
-  /// Creates a [Page1Screen].
-  const Page1Screen({Key? key}) : super(key: key);
+/// The details screen
+class DetailsScreen extends StatelessWidget {
+  /// Constructs a [DetailsScreen]
+  const DetailsScreen({Key? key}) : super(key: key);
 
   @override
-  Widget build(BuildContext context) => Scaffold(
-        appBar: AppBar(title: const Text(App.title)),
-        body: Center(
-          child: Column(
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: <Widget>[
-              ElevatedButton(
-                onPressed: () => context.go('/page2'),
-                child: const Text('Go to page 2'),
-              ),
-            ],
-          ),
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(title: const Text('Details Screen')),
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <ElevatedButton>[
+            ElevatedButton(
+              onPressed: () => context.go('/'),
+              child: const Text('Go back to the Home screen'),
+            ),
+          ],
         ),
-      );
-}
-
-/// The screen of the second page.
-class Page2Screen extends StatelessWidget {
-  /// Creates a [Page2Screen].
-  const Page2Screen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) => Scaffold(
-        appBar: AppBar(title: const Text(App.title)),
-        body: Center(
-          child: Column(
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: <Widget>[
-              ElevatedButton(
-                onPressed: () => context.go('/'),
-                child: const Text('Go back to home page'),
-              ),
-            ],
-          ),
-        ),
-      );
+      ),
+    );
+  }
 }
diff --git a/packages/go_router/example/lib/sub_routes.dart b/packages/go_router/example/lib/sub_routes.dart
deleted file mode 100644
index 8bd7728..0000000
--- a/packages/go_router/example/lib/sub_routes.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:go_router/go_router.dart';
-
-// This scenario demonstrates an app with multi-level routing.
-//
-// The GoRoute '/' builds a HomeScreen page and has a sub-route, 'family'. The
-// 'family' also has its own sub-route, person'.
-//
-// If a url matches a sub-route, the page built by the sub-route is placed on
-// top of the parent's page. In this example, a url '/family/person' will create
-// a stack of three pages, [PersonScreen, FamilyScreen, HomeScreen] where the
-// PersonScreen being the top-most page and shown on the screen. Since there are
-// two more pages under it, the back button is shown on the app bar and can pop
-// the page to show the pages underneath.
-
-void main() => runApp(App());
-
-/// The main app.
-class App extends StatelessWidget {
-  /// Creates an [App].
-  App({Key? key}) : super(key: key);
-
-  /// The title of the app.
-  static const String title = 'GoRouter Example: Sub-routes';
-
-  @override
-  Widget build(BuildContext context) => MaterialApp.router(
-        routerConfig: _router,
-        title: title,
-      );
-
-  final GoRouter _router = GoRouter(
-    routes: <GoRoute>[
-      GoRoute(
-        path: '/',
-        builder: (BuildContext context, GoRouterState state) =>
-            const HomeScreen(),
-        routes: <GoRoute>[
-          GoRoute(
-            path: 'family',
-            builder: (BuildContext context, GoRouterState state) =>
-                const FamilyScreen(),
-            routes: <GoRoute>[
-              GoRoute(
-                path: 'person',
-                builder: (BuildContext context, GoRouterState state) =>
-                    const PersonScreen(),
-              ),
-            ],
-          ),
-        ],
-      ),
-    ],
-  );
-}
-
-/// The home screen that shows a list of families.
-class HomeScreen extends StatelessWidget {
-  /// Creates a [HomeScreen].
-  const HomeScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) => Scaffold(
-        appBar: AppBar(title: const Text(App.title)),
-        body: Center(
-          child: ElevatedButton(
-            onPressed: () => context.go('/family'),
-            child: const Text('Go to family screen'),
-          ),
-        ),
-      );
-}
-
-/// The screen that shows a list of persons in a family.
-class FamilyScreen extends StatelessWidget {
-  /// Creates a [FamilyScreen].
-  const FamilyScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) => Scaffold(
-        appBar: AppBar(title: const Text('Family screen')),
-        body: Center(
-          child: ElevatedButton(
-            onPressed: () => context.go('/family/person'),
-            child: const Text('Go to person screen'),
-          ),
-        ),
-      );
-}
-
-/// The person screen.
-class PersonScreen extends StatelessWidget {
-  /// Creates a [PersonScreen].
-  const PersonScreen({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) => Scaffold(
-      appBar: AppBar(title: const Text('Person screen')),
-      body: const Center(
-        child: Text('This is the person screen'),
-      ));
-}
diff --git a/packages/go_router/example/lib/transition_animations.dart b/packages/go_router/example/lib/transition_animations.dart
new file mode 100644
index 0000000..74dc79e
--- /dev/null
+++ b/packages/go_router/example/lib/transition_animations.dart
@@ -0,0 +1,111 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+
+/// To use a custom transition animation, provide a `pageBuilder` with a
+/// CustomTransitionPage.
+///
+/// To learn more about animation in Flutter, check out the [Introduction to
+/// animations](https://docs.flutter.dev/development/ui/animations) page on
+/// flutter.dev.
+void main() => runApp(const MyApp());
+
+/// The route configuration.
+final GoRouter _router = GoRouter(
+  routes: <RouteBase>[
+    GoRoute(
+      path: '/',
+      builder: (BuildContext context, GoRouterState state) {
+        return const HomeScreen();
+      },
+      routes: <RouteBase>[
+        GoRoute(
+          path: 'details',
+          pageBuilder: (BuildContext context, GoRouterState state) {
+            return CustomTransitionPage<void>(
+              key: state.pageKey,
+              child: const DetailsScreen(),
+              transitionDuration: const Duration(milliseconds: 150),
+              transitionsBuilder: (BuildContext context,
+                  Animation<double> animation,
+                  Animation<double> secondaryAnimation,
+                  Widget child) {
+                // Change the opacity of the screen using a Curve based on the the animation's
+                // value
+                return FadeTransition(
+                  opacity:
+                      CurveTween(curve: Curves.easeInOut).animate(animation),
+                  child: child,
+                );
+              },
+            );
+          },
+        ),
+      ],
+    ),
+  ],
+);
+
+/// The main app.
+class MyApp extends StatelessWidget {
+  /// Constructs a [MyApp]
+  const MyApp({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp.router(
+      routerConfig: _router,
+    );
+  }
+}
+
+/// The home screen
+class HomeScreen extends StatelessWidget {
+  /// Constructs a [HomeScreen]
+  const HomeScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(title: const Text('Home Screen')),
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            ElevatedButton(
+              onPressed: () => context.go('/details'),
+              child: const Text('Go to the Details screen'),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
+
+/// The details screen
+class DetailsScreen extends StatelessWidget {
+  /// Constructs a [DetailsScreen]
+  const DetailsScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(title: const Text('Details Screen')),
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            ElevatedButton(
+              onPressed: () => context.go('/'),
+              child: const Text('Go back to the Home screen'),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/packages/go_router/example/test/main_test.dart b/packages/go_router/example/test/main_test.dart
index f8e3ed0..9cf8d5e 100644
--- a/packages/go_router/example/test/main_test.dart
+++ b/packages/go_router/example/test/main_test.dart
@@ -7,15 +7,15 @@
 
 void main() {
   testWidgets('example works', (WidgetTester tester) async {
-    await tester.pumpWidget(example.App());
-    expect(find.text('Go to page 2'), findsOneWidget);
+    await tester.pumpWidget(const example.MyApp());
+    expect(find.text('Go to the Details screen'), findsOneWidget);
 
-    await tester.tap(find.text('Go to page 2'));
+    await tester.tap(find.text('Go to the Details screen'));
     await tester.pumpAndSettle();
-    expect(find.text('Go back to home page'), findsOneWidget);
+    expect(find.text('Go back to the Home screen'), findsOneWidget);
 
-    await tester.tap(find.text('Go back to home page'));
+    await tester.tap(find.text('Go back to the Home screen'));
     await tester.pumpAndSettle();
-    expect(find.text('Go to page 2'), findsOneWidget);
+    expect(find.text('Go to the Details screen'), findsOneWidget);
   });
 }
diff --git a/packages/go_router/example/test/sub_routes_test.dart b/packages/go_router/example/test/sub_routes_test.dart
deleted file mode 100644
index 9c5dc70..0000000
--- a/packages/go_router/example/test/sub_routes_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-import 'package:go_router_examples/sub_routes.dart' as example;
-
-void main() {
-  testWidgets('example works', (WidgetTester tester) async {
-    await tester.pumpWidget(example.App());
-    expect(find.text('Go to family screen'), findsOneWidget);
-
-    await tester.tap(find.text('Go to family screen'));
-    await tester.pumpAndSettle();
-    expect(find.text('Go to person screen'), findsOneWidget);
-
-    await tester.tap(find.text('Go to person screen'));
-    await tester.pumpAndSettle();
-    expect(find.text('This is the person screen'), findsOneWidget);
-    expect(find.byType(BackButton), findsOneWidget);
-
-    await tester.tap(find.byType(BackButton));
-    await tester.pumpAndSettle();
-    expect(find.text('Go to person screen'), findsOneWidget);
-    expect(find.byType(BackButton), findsOneWidget);
-
-    await tester.tap(find.byType(BackButton));
-    await tester.pumpAndSettle();
-    expect(find.text('Go to family screen'), findsOneWidget);
-    expect(find.byType(BackButton), findsNothing);
-  });
-}
diff --git a/packages/go_router/example/test/transition_animations_test.dart b/packages/go_router/example/test/transition_animations_test.dart
new file mode 100644
index 0000000..107ac26
--- /dev/null
+++ b/packages/go_router/example/test/transition_animations_test.dart
@@ -0,0 +1,21 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:go_router_examples/transition_animations.dart' as example;
+
+void main() {
+  testWidgets('example works', (WidgetTester tester) async {
+    await tester.pumpWidget(const example.MyApp());
+    expect(find.text('Go to the Details screen'), findsOneWidget);
+
+    await tester.tap(find.text('Go to the Details screen'));
+    await tester.pumpAndSettle();
+    expect(find.text('Go back to the Home screen'), findsOneWidget);
+
+    await tester.tap(find.text('Go back to the Home screen'));
+    await tester.pumpAndSettle();
+    expect(find.text('Go to the Details screen'), findsOneWidget);
+  });
+}
diff --git a/packages/go_router/lib/src/route.dart b/packages/go_router/lib/src/route.dart
index 3050569..f1442b4 100644
--- a/packages/go_router/lib/src/route.dart
+++ b/packages/go_router/lib/src/route.dart
@@ -114,6 +114,12 @@
 /// The Page depends on the application type: [MaterialPage] for
 /// [MaterialApp], [CupertinoPage] for [CupertinoApp], or
 /// [NoTransitionPage] for [WidgetsApp].
+///
+/// {@category Get started}
+/// {@category Configuration}
+/// {@category Transition animations}
+/// {@category Named routes}
+/// {@category Redirection}
 class GoRoute extends RouteBase {
   /// Constructs a [GoRoute].
   /// - [path] and [name] cannot be empty strings.
@@ -427,6 +433,7 @@
 /// ),
 /// ```
 ///
+/// {@category Configuration}
 class ShellRoute extends RouteBase {
   /// Constructs a [ShellRoute].
   ShellRoute({
diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart
index f3a7f32..ba862d0 100644
--- a/packages/go_router/lib/src/route_data.dart
+++ b/packages/go_router/lib/src/route_data.dart
@@ -12,10 +12,11 @@
 import 'state.dart';
 
 /// Baseclass for supporting
-/// [typed routing](https://gorouter.dev/typed-routing).
+/// [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html).
 ///
 /// Subclasses must override one of [build], [buildPageWithState], or
 /// [redirect].
+/// {@category Type-safe routes}
 abstract class GoRouteData {
   /// Allows subclasses to have `const` constructors.
   ///
diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart
index 9d78082..fded5fa 100644
--- a/packages/go_router/lib/src/router.dart
+++ b/packages/go_router/lib/src/router.dart
@@ -13,29 +13,36 @@
 import 'parser.dart';
 import 'typedefs.dart';
 
-/// The top-level go router class.
+/// The route configuration for the app.
 ///
-/// This is the main entry point for defining app's routing policy.
+/// The `routes` list specifies the top-level routes for the app. It must not be
+/// empty and must contain an [GoRouter] to match `/`.
 ///
-/// The `routes` defines the routing table. It must not be empty and must
-/// contain an [GoRouter] to match `/`.
+/// See the [Get
+/// started](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/main.dart)
+/// example, which shows an app with a simple route configuration.
 ///
-/// See [Routes](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/main.dart)
-/// for an example of defining a simple routing table.
-///
-/// See [Sub-routes](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/sub_routes.dart)
-/// for an example of defining a multi-level routing table.
-///
-/// The `redirect` does top-level redirection before the URIs are parsed by
-/// the `routes`. Consider using [GoRoute.redirect] for individual route
-/// redirection. If [BuildContext.dependOnInheritedWidgetOfExactType] is used
-/// during the redirection (which is how `of` methods are usually implemented),
-/// a re-evaluation will be triggered when the [InheritedWidget] changes.
+/// The [redirect] callback allows the app to redirect to a new location.
+/// Alternatively, you can specify a redirect for an individual route using
+/// [GoRoute.redirect]. If [BuildContext.dependOnInheritedWidgetOfExactType] is
+/// used during the redirection (which is how `of` methods are usually
+/// implemented), a re-evaluation will be triggered when the [InheritedWidget]
+/// changes.
 ///
 /// See also:
-///  * [GoRoute], which provides APIs to define the routing table.
-///  * [examples](https://github.com/flutter/packages/tree/main/packages/go_router/example),
+/// * [Configuration](https://pub.dev/documentation/go_router/topics/Configuration-topic.html)
+/// * [GoRoute], which provides APIs to define the routing table.
+/// * [examples](https://github.com/flutter/packages/tree/main/packages/go_router/example),
 ///    which contains examples for different routing scenarios.
+/// {@category Get started}
+/// {@category Upgrading}
+/// {@category Configuration}
+/// {@category Navigation}
+/// {@category Redirection}
+/// {@category Web}
+/// {@category Deep linking}
+/// {@category Error handling}
+/// {@category Named routes}
 class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
   /// Default constructor to configure a GoRouter with a routes builder
   /// and an error page builder.
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index 94df1c9..ff28571 100644
--- a/packages/go_router/pubspec.yaml
+++ b/packages/go_router/pubspec.yaml
@@ -1,7 +1,7 @@
 name: go_router
 description: A declarative router for Flutter based on Navigation 2 supporting
   deep linking, data-driven routes and more
-version: 5.1.6
+version: 5.1.7
 repository: https://github.com/flutter/packages/tree/main/packages/go_router
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22