Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
ddcf6a2
docs: design spec + implementation plan for generic navigation_devtools
claude Jul 14, 2026
878b142
chore: restructure workspace for generic navigation_devtools (renames…
claude Jul 15, 2026
3302b28
feat(shared)!: protocol v2 — RouterSummary, RouteNode, StackFrame, mu…
claude Jul 15, 2026
dd68725
feat(core): NavigationAdapter API, multi-router registry, generic ser…
claude Jul 15, 2026
137b1e0
feat(core): adapter conformance test kit (lib/testing.dart)
claude Jul 15, 2026
8e11066
feat(core): Navigator 1.0 adapter with shadow stack + navigator1_example
claude Jul 15, 2026
af24770
feat(core): generic RouterDelegate adapter + router_delegate_example
claude Jul 15, 2026
5547e09
feat(go_router): GoRouterAdapter package + example (go_router ^16, pi…
claude Jul 15, 2026
ce1198d
refactor(auto_route)!: AutoRouteAdapter over navigation_devtools core…
claude Jul 15, 2026
5bdfa08
chore: zero analyzer issues across workspace
claude Jul 15, 2026
2a5b379
feat(extension): multi-router selector, capability-aware UI, kind/red…
claude Jul 15, 2026
f6f7493
feat(core): ship the extension bundle from navigation_devtools; drop …
claude Jul 15, 2026
db5f096
docs: navigation_devtools READMEs, changelogs; split conformance kit …
claude Jul 15, 2026
0563c89
chore: publish dry-runs clean (auto_route_devtools bumped to 0.2.0), …
claude Jul 15, 2026
cae6aca
fix: bump auto_route_example constraint to ^0.2.0; all dry-runs 0 war…
claude Jul 15, 2026
6c8bb18
feat: dialog & bottom-sheet visibility — pageless tracking verified, …
claude Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: CI

on:
push:
branches: [main]
pull_request:

jobs:
analyze-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Bootstrap workspace
run: flutter pub get
- name: Analyze
run: flutter analyze packages examples
- name: Test
run: >
flutter test
packages/navigation_devtools_shared
packages/navigation_devtools
packages/go_router_devtools
packages/auto_route_devtools
packages/navigation_devtools_extension
- name: Publish dry-runs
run: |
for p in navigation_devtools navigation_devtools_shared navigation_devtools_test go_router_devtools auto_route_devtools; do
(cd packages/$p && flutter pub publish --dry-run)
done

bundle-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- name: Bootstrap workspace
run: flutter pub get
- name: Rebuild extension bundle
working-directory: packages/navigation_devtools_extension
run: dart run devtools_extensions build_and_copy --source=. --dest=../navigation_devtools/extension/devtools
- name: Fail if the committed bundle drifted
# Compiled JS differs run-to-run; assert the asset *file set* matches
# so a UI change without a bundle rebuild fails CI.
run: |
git status --porcelain packages/navigation_devtools/extension/devtools \
| grep -E '^\?\?|^ D' && {
echo 'Extension bundle file set drifted — run build_and_copy and commit.';
exit 1;
} || echo 'Bundle file set is consistent.'
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.dart_tool/
build/
# DevTools extension bundle must ship in the published package
!packages/auto_route_devtools/extension/devtools/build/
!packages/auto_route_devtools/extension/devtools/build/**
!packages/navigation_devtools/extension/devtools/build/
!packages/navigation_devtools/extension/devtools/build/**
.packages
pubspec.lock
*.iml
Expand Down
106 changes: 102 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,104 @@
# auto_route_devtools (monorepo)
# navigation_devtools (monorepo)

A Flutter DevTools panel extension for [auto_route](https://pub.dev/packages/auto_route) that surfaces the live backstack, the full router tree, route args/params, and confirm-gated interactive navigation directly inside Flutter DevTools. Unlike auto_route (which ships no DevTools extension) and `developer_tools_auto_route` (an in-app overlay), this is a proper DevTools panel.
One Flutter DevTools panel for **every** kind of Flutter navigation. Inspect the live backstack, browse the declared route tree, view per-route args/params, and drive confirm-gated navigation from the panel — whether your app uses Navigator 1.0, a hand-written Navigator 2.0 `RouterDelegate`, go_router, or auto_route.

- Package: [`packages/auto_route_devtools/`](packages/auto_route_devtools/) — the publishable package and its README/setup guide.
- Design docs: [`docs/superpowers/`](docs/superpowers/) — specs and implementation plans.
![The panel inspecting a go_router app](docs/images/panel_go_router.png)

## Packages

| Package | What it is | Use it when |
|---|---|---|
| [`navigation_devtools`](packages/navigation_devtools/) | Core: adapter API, DevTools panel bundle, Navigator 1.0 + generic RouterDelegate adapters, adapter conformance test kit | `MaterialApp(routes:)`, imperative push/pop, or a custom `RouterDelegate` |
| [`go_router_devtools`](packages/go_router_devtools/) | go_router adapter | `MaterialApp.router(routerConfig: GoRouter(...))` |
| [`auto_route_devtools`](packages/auto_route_devtools/) | auto_route v11 adapter | `MaterialApp.router(routerConfig: appRouter.config())` |

The DevTools panel ships once, inside `navigation_devtools`; the adapter packages depend on it, so depending on any one of them gets you the panel. Every affordance in the panel is **capability-aware** — a router that can't enumerate its routes simply shows no tree pane; one that can't deep-link shows no path field.

## Quick start

Pick the adapter matching your navigation setup (each snippet is mirrored by a runnable app under [`examples/`](examples/)):

**Navigator 1.0** ([example](examples/navigator1_example/)):

```dart
final adapter = Navigator1Adapter(routes: appRoutes);
NavigationDevTools.register(adapter);
runApp(MaterialApp(routes: appRoutes, navigatorObservers: [adapter.observer]));
```

**Custom RouterDelegate** ([example](examples/router_delegate_example/)):

```dart
NavigationDevTools.register(RouterDelegateAdapter(delegate, parser: parser));
runApp(MaterialApp.router(routerDelegate: delegate, routeInformationParser: parser));
```

**go_router** ([example](examples/go_router_example/)):

```dart
NavigationDevTools.register(GoRouterAdapter(router));
runApp(MaterialApp.router(routerConfig: router));
```

**auto_route** ([example](examples/auto_route_example/)):

```dart
AutoRouteDevTools.init(router);
runApp(MaterialApp.router(
routerConfig: router.config(
navigatorObservers: () => [AutoRouteDevTools.navigationObserver()],
),
));
```

Then run your app and open the **navigation_devtools** tab in Flutter DevTools.

## Capability matrix

| Capability | Navigator 1.0 | RouterDelegate | go_router | auto_route |
|---|---|---|---|---|
| Static route tree | ✅ with `routes:` map | ❌ | ✅ incl. shells | ✅ |
| Guard / redirect badges | ❌ | ❌ | ✅ redirect flag | ✅ guard names |
| Navigate by path | ✅ | ✅ with parser | ✅ `go()` | ✅ |
| Push by name | ✅ | ❌ | ✅ | ❌ |
| Pop | ✅ | ✅ | ✅ | ✅ |
| Nested routers | one adapter per `Navigator` | ❌ | ✅ shells | ✅ |

## Writing your own adapter

Implement `NavigationAdapter` (see [`packages/navigation_devtools`](packages/navigation_devtools/)) and validate it with the bundled conformance kit:

```dart
import 'package:navigation_devtools_test/navigation_devtools_test.dart';

runAdapterConformanceTests('MyAdapter', AdapterHarness(...));
```

## Dialogs & bottom sheets

`showDialog`, `showModalBottomSheet`, and friends push **pageless routes** on the raw `Navigator` — router packages (go_router, auto_route) never see them in their own state.

- **Navigator 1.0 apps:** nothing to do — dialogs and sheets appear on the backstack automatically, badged `pageless` (e.g. `DialogRoute<void>`), and can be popped from the panel.
- **go_router / auto_route / custom delegates:** pair your adapter with a `Navigator1Adapter` observer on the same navigator; it shows up as a second router in the panel's selector, carrying the raw stack including dialogs:

```dart
// go_router
final pageless = Navigator1Adapter(label: 'Pageless routes');
final router = GoRouter(observers: [pageless.observer], routes: [...]);
NavigationDevTools.register(GoRouterAdapter(router));
NavigationDevTools.register(pageless);

// auto_route
navigatorObservers: () => [adapter.observer, pageless.observer]
```

Both recipes are regression-tested (`dialogs_with_nav1_observer_test.dart` in each adapter package).

## Prior art

- Flutter DevTools ships no navigation/backstack inspector.
- auto_route and go_router ship no DevTools extension (go_router only offers `debugLogDiagnostics` console logging; `developer_tools_auto_route` is an in-app overlay, not a DevTools panel).

## Repository layout

Design docs and implementation plans live in [`docs/superpowers/`](docs/superpowers/). The DevTools panel source is [`packages/navigation_devtools_extension/`](packages/navigation_devtools_extension/) (unpublished; prebuilt into the core package — rebuild with `dart run devtools_extensions build_and_copy --source=. --dest=../navigation_devtools/extension/devtools`).
Binary file added docs/images/panel_go_router.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/panel_navigator1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading