Reactive Routing
Deep-dive into Fluxy's type-safe, declarative routing and navigation engine.
Reactive Routing
Fluxy includes a production-stable routing engine (Router 2.0) that handles everything from simple navigation to complex nested views and transition animations.
Defining Routes
Routes are defined using the FxRoute class. Each route requires a path and a builder that receives both URL parameters and optional transition arguments.
final routes = [
FxRoute(
path: "/",
builder: (params, args) => const HomePage(),
),
FxRoute(
path: "/user/:id",
builder: (params, args) => UserPage(id: params['id']!),
),
];Integrated Controllers (New in v0.1.11)
FxRoute can now manage the lifecycle of your logic layer. By providing a controller factory, the framework will automatically:
- Instantiate the controller when the route is reached.
- Register it in the global DI container (
FluxyDI.put). - Dispose/Remove it once the route is removed from the navigation stack.
FxRoute(
path: "/user/:id",
builder: (p, a) => UserView(),
controller: (context) => UserController(), // Auto-managed lifecycle
)This ensures that your business logic is only in memory while the user is on that specific page, eliminating manual boilerplate.
Transition Modes
Fluxy supports various built-in transitions via FxTransition:
FxTransition.native: Default platform transition.FxTransition.fade: Smooth cross-fade.FxTransition.slideUp,.slideRight,.slideLeft: Directional slides.FxTransition.zoom: Scale-based transition.FxTransition.none: Instant swap.FxTransition.custom: Professional-grade transitions viatransitionBuilder.
FxRoute(
path: "/details",
builder: (p, a) => DetailsPage(),
transition: FxTransition.fade,
transitionDuration: const Duration(milliseconds: 500),
)Route Protection
Secure your application using both global Middlewares and per-route Guards.
Guards (Per-Route)
Guards are functions that return a FutureOr<bool>. If any guard returns false, the navigation is blocked.
FxRoute(
path: "/dashboard",
builder: (p, a) => Dashboard(),
guards: [() => AuthService.isLoggedIn()],
)Middleware (Global)
Middlewares run before every navigation event.
FluxyRouter.use((path) async {
print("Navigating to: $path");
return true; // Allow navigation
});Advanced Patterns
Route Grouping
Use FxRoute.group() to apply prefixes or shared guards to a collection of routes.
final adminRoutes = FxRoute.group(
prefix: "/admin",
guards: [AdminGuard()],
routes: [
FxRoute(path: "/users", builder: (p, a) => UserList()),
FxRoute(path: "/reports", builder: (p, a) => Reports()),
],
);Nested Routing (FxOutlet)
For complex layouts (like tabs or dashboard sidebars), use FxOutlet to render sub-routes within a specific scope.
FxOutlet(
scope: "dashboard",
initialRoute: "/overview",
routes: [
FxRoute(path: "/overview", builder: (p, a) => Overview()),
FxRoute(path: "/stats", builder: (p, a) => Statistics()),
],
)Navigation Shortcuts
Use the Fluxy class for a high-level API or FluxyRouter for scoped control.
Fluxy.to("/path"): Push a new route.Fluxy.off("/path"): Replace current route.Fluxy.offAll("/path"): Clear stack and push.Fluxy.back(): Pop the current route.- Scoped Navigation: All methods accept a
scopeparameter to control specificFxOutletnavigators.
Organization: Centralized vs Isolated
Fluxy is flexible about where your routes live. Choose the pattern that fits your team size:
1. Centralized (Recommended for small apps)
Define all routes in a single list (e.g., lib/core/routes.dart). This provides a "Master Map" that is easy to search.
2. Isolated (Recommended for enterprise apps)
Each feature manages its own routes in a feature.route.dart file. This isolation allows large teams to add new pages without touching a shared configuration file.
// Example of Isolated Routing
final routes = [
...CatalogRoutes.all,
...AuthRoutes.all,
...ProfileRoutes.all,
];[!IMPORTANT] Regardless of the organization, always use the dot naming convention (
catalog.route.dart) for route files to distinguish them from standard widgets.