# Declarative Routing

go_router is governed by a set of routes which you specify as part of the
`GoRouter` constructor:

```dart
class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const Page1Screen(),
      ),
      GoRoute(
        path: '/page2',
        builder: (context, state) => const Page2Screen(),
      ),
    ],
  );
}
```

In this case, we've defined two routes. Each route `path` will be matched
against the location to which the user is navigating. Only a single route can be
matched, specifically the one whose `path` matches the entire location (and so
it doesn't matter in which order you list your routes). The `path` will be
matched in a case-insensitive way, although the case for
[parameters](/parameters) will be preserved.

In addition to the `path`, each route will typically have a `builder` function,
which is responsible for building the `Widget` that is to take up the entire
screen of your app. The [default transition](/transitions) will be used between
pages depending on the type of app you've put at the top of your widget tree,
e.g. the use of `MaterialApp` will cause go_router to use the `MaterialPage`
transitions.

## Router state

While it's not used in the snippet above, the `builder` function are passed a
`state` object, which is an instance of the `GoRouterState` class that contains
some useful information:

| `GoRouterState` property | description                                        | example 1                | example 2                  |
| ------------------------ | -------------------------------------------------- | ------------------------ | -------------------------- |
| `location`               | location of the full route, including query params | `/login?from=/family/f2` | `/family/f2/person/p1`     |
| `subloc`                 | location of this sub-route w/o query params        | `/login`                 | `/family/f2`               |
| `name`                   | route name                                         | `login`                  | `family`                   |
| `path`                   | route path                                         | `/login`                 | `family/:fid`              |
| `fullpath`               | full path to this sub-route                        | `/login`                 | `/family/:fid`             |
| `params`                 | params extracted from the location                 | `{}`                     | `{'fid': 'f2'}`            |
| `queryParams`            | optional params from the end of the location       | `{'from': '/family/f1'}` | `{}`                       |
| `extra`                  | optional object param                              | `null`                   | `null`                     |
| `error`                  | `Exception` associated with this sub-route, if any | `Exception('404')`       | ...                        |
| `pageKey`                | unique key for this sub-route                      | `ValueKey('/login')`     | `ValueKey('/family/:fid')` |

The `state` object is useful for passing parameters to [parameterized
routes](/parameters) and for [redirection](/redirection). Not all of the state
parameters will be set every time. In general, `GoRouterState` defines a
superset of the potential current state of a `GoRouter` instance. For example,
the `error` parameter will only be set if there's an error.

## Initialization

With a list of routes, you can create an instance of a `GoRouter`, which itself
provides the objects you need to call the `MaterialApp.router` constructor (or
the `CupertinoApp.router` constructor):

```dart
class App extends StatelessWidget {
  App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
      );

  final _router = GoRouter(routes: ...);
}
```

With the router in place, your app can now [navigate between
pages](/navigation).

## 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 you're
using neither. You can replace the default error screen by setting the
`errorBuilder` parameter of the `GoRouter`:

```dart
class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    ...
    errorBuilder: (context, state) => ErrorScreen(state.error),
  );
}
```

The error screen, whether it's provided by you or go_router, will be used in
case a location doesn't match a route, more than one route is found for a given
location or if any of the builder functions throws an exception.

## Deep Linking

Flutter defines "deep linking" as "opening a URL displays that screen in your
app." Anything that's listed as a `GoRoute` can be accessed via deep linking
across Android, iOS and the web. Support works out of the box for the web, of
course, via the address bar, but requires additional configuration for Android
and iOS as described in the [Flutter
docs](https://flutter.dev/docs/development/ui/navigation/deep-linking).
