Flutter autoroute
Skill Poorgramer-Zack/dart-expert-skills/skills/flutter-autoroute
A comprehensive library of modular Agent Skills for Flutter & Dart development
npx -y skills add Poorgramer-Zack/dart-expert-skills --skill flutter-autorouteAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Implements type-safe Flutter routing using AutoRoute v11 with code generation and @RoutePage annotations. Activates when setting up AutoRoute navigation, configuring AutoRouterConfig or RootStackRouter, generating route files with build_runner, using @RoutePage, @PathParam, or @QueryParam annotations, implementing AutoTabsRouter for bottom navigation tabs, adding navigation guards with AutoRouteGuard, setting up nested or child routes, handling type-safe route parameters, or migrating from string-based Navigator routing to compile-time-verified routes. Ideal for large apps requiring refactoring confidence and zero string-based routing errors.
SKILL.md
6.3 KB, as published. Nobody here has run it
AutoRoute Type-Safe Navigation Guide (v11.x)
Goal
Implement type-safe routing using AutoRoute with compile-time code generation. AutoRoute v11+ uses @RoutePage annotations to eliminate boilerplate and ensure type safety through generated route configurations.
Process
Phase 1: Install Dependencies
dependencies:
auto_route: ^11.1.0
dev_dependencies:
auto_route_generator: ^11.1.0
build_runner: ^2.14.1
Phase 2: Annotate Pages
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () => context.router.push(ProfileRoute()),
child: Text('Go to Profile'),
),
),
);
}
}
@RoutePage()
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Profile')),
);
}
}
// Type-safe parameters
@RoutePage()
class UserScreen extends StatelessWidget {
final String userId;
final String? referrer; // Optional parameter
const UserScreen({
@PathParam('id') required this.userId,
@QueryParam('ref') this.referrer,
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User $userId')),
body: Text('Referrer: ${referrer ?? "none"}'),
);
}
}
Phase 3: Define Router Configuration
import 'package:auto_route/auto_route.dart';
part 'app_router.gr.dart';
@AutoRouterConfig()
class AppRouter extends RootStackRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(page: HomeRoute.page, initial: true),
AutoRoute(page: ProfileRoute.page),
AutoRoute(page: UserRoute.page, path: '/user/:id'),
AutoRoute(page: LoginRoute.page, path: '/login'),
];
}
Phase 4: Generate Routes
flutter pub run build_runner build --delete-conflicting-outputs
# Or watch mode for development
flutter pub run build_runner watch
Phase 5: Initialize Router
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final _appRouter = AppRouter();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _appRouter.config(),
);
}
}
Phase 6: Navigation
// Push route (type-safe!)
context.router.push(UserRoute(userId: '123'));
// Push with query params
context.router.push(UserRoute(userId: '123', referrer: 'home'));
// Replace
context.router.replace(ProfileRoute());
// Pop
context.router.pop();
// Pop until
context.router.popUntil((route) => route.settings.name == HomeRoute.name);
// Navigate to nested route
context.router.navigate(ProfileRoute(children: [
EditProfileRoute(),
]));
Phase 7: Nested Navigation & Tabs
@AutoRouterConfig()
class AppRouter extends RootStackRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(
page: DashboardRoute.page,
initial: true,
children: [
AutoRoute(page: HomeRoute.page, initial: true),
AutoRoute(page: SearchRoute.page),
AutoRoute(page: ProfileRoute.page),
],
),
];
}
@RoutePage()
class DashboardScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AutoTabsRouter(
routes: const [
HomeRoute(),
SearchRoute(),
ProfileRoute(),
],
builder: (context, child) {
final tabsRouter = AutoTabsRouter.of(context);
return Scaffold(
body: child,
bottomNavigationBar: BottomNavigationBar(
currentIndex: tabsRouter.activeIndex,
onTap: tabsRouter.setActiveIndex,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
],
),
);
},
);
}
}
Phase 8: Guards (Authentication)
class AuthGuard extends AutoRouteGuard {
@override
void onNavigation(NavigationResolver resolver, StackRouter router) {
if (AuthService.instance.isLoggedIn) {
resolver.next(); // Proceed
} else {
resolver.redirect(LoginRoute(
onResult: (success) {
if (success) {
resolver.next();
}
},
));
}
}
}
// Apply guard
@AutoRouterConfig()
class AppRouter extends RootStackRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(page: LoginRoute.page),
AutoRoute(
page: ProfileRoute.page,
guards: [AuthGuard()], // Protected route
),
];
}
Constraints
- Breaking Changes in v11: Old syntax from v10 is incompatible. Use @RoutePage() only.
- Type Safety: All route parameters are type-checked at compile time.
- Code Generation: Must run build_runner after route changes.
- Unique Route Names: Page names must be unique across the app.
- Guard Order: Guards execute in the order they're listed.