skills/flutter/flutter-setup-declarative-routing/SKILL.md
Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
npx skillsauth add dhruvanbhalara/skills flutter-setup-declarative-routingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use the go_router package for declarative routing in Flutter. It provides a reliable API for complex routing scenarios, deep linking, and nested navigation.
BottomNavigationBar). StatefulShellRoute maintains the state of parallel navigation branches.# fragment from web URLs, essential for clean deep linking across platforms.Follow this workflow to bootstrap a new Flutter application with go_router and configure the root routing mechanism.
go_router dependency.GoRouter configuration.MaterialApp.router.Run the following commands to create the app and add the required routing package:
flutter create <app-name>
cd <app-name>
flutter pub add go_router
Define a top-level GoRouter instance. Handle authentication or state-based routing using the redirect parameter.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
void main() {
// Use path URL strategy to remove the '#' from web URLs
usePathUrlStrategy();
runApp(const MyApp());
}
final GoRouter _router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
routes: [
GoRoute(
path: 'details/:id',
builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
),
],
),
],
errorBuilder: (context, state) => ErrorScreen(error: state.error),
);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
title: 'Routing App',
);
}
}
Configure the native platforms to intercept specific URLs and route them into the Flutter application.
AndroidManifest.xml: Add the intent filter inside the <activity> tag for .MainActivity.<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="yourdomain.com" />
<data android:scheme="https" />
</intent-filter>
assetlinks.json: Serve the following JSON at https://yourdomain.com/.well-known/assetlinks.json.[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.yourcompany.yourapp",
"sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
}
}]
Info.plist: Opt-in to Flutter's default deep link handler.
Note: If using a third-party deep linking plugin (e.g., app_links), set this to NO to prevent conflicts.<key>FlutterDeepLinkingEnabled</key>
<true/>
Runner.entitlements: Add the associated domain.<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:yourdomain.com</string>
</array>
apple-app-site-association: Serve the following JSON (without a .json extension) at https://yourdomain.com/.well-known/apple-app-site-association.{
"applinks": {
"apps": [],
"details": [{
"appIDs": ["TEAM_ID.com.yourcompany.yourapp"],
"paths": ["*"],
"components": [{"/": "/*"}]
}]
}
}
Run validator -> review errors -> fix.
adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp
xcrun on a booted simulator.
xcrun simctl openurl booted https://yourdomain.com/details/123
Use StatefulShellRoute to implement persistent UI shells (like a bottom navigation bar) that maintain the state of their child routes.
StatefulShellRoute.indexedStack in the GoRouter configuration.StatefulShellBranch instances for each navigation tab.StatefulNavigationShell.final GoRouter _router = GoRouter(
initialLocation: '/home',
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNavBar(navigationShell: navigationShell);
},
branches: [
StatefulShellBranch(
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const HomeScreen(),
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/settings',
builder: (context, state) => const SettingsScreen(),
),
],
),
],
),
],
);
Implement the UI shell that consumes the StatefulNavigationShell to handle branch switching.
class ScaffoldWithNavBar extends StatelessWidget {
const ScaffoldWithNavBar({
required this.navigationShell,
super.key,
});
final StatefulNavigationShell navigationShell;
void _goBranch(int index) {
navigationShell.goBranch(
index,
// Support navigating to the initial location when tapping the active tab.
initialLocation: index == navigationShell.currentIndex,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: navigationShell,
bottomNavigationBar: NavigationBar(
selectedIndex: navigationShell.currentIndex,
onDestinationSelected: _goBranch,
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
],
),
);
}
}
Use the context.go() and context.push() extension methods provided by go_router.
// Replaces the current route stack with the target route (Declarative)
context.go('/details/123');
// Pushes the target route onto the existing stack (Imperative)
context.push('/details/123');
// Navigates using a named route and path parameters
context.goNamed('details', pathParameters: {'id': '123'});
// Pops the current route
context.pop();
development
Perform REST API networking operations (GET, POST, PUT, DELETE) using the lightweight and robust standard `http` package, including platform configurations and background parsing models.
development
Configure internationalization and localization support using Flutter's built-in l10n system, App Resource Bundle (ARB) files, and ICU formatting syntax.
development
Create model classes with fromJson/toJson using dart:convert and Dart 3 pattern matching. Use when manually mapping JSON to classes, parsing HTTP responses, or choosing between manual and code-generated serialization.
data-ai
Diagnose and fix Flutter layout constraint violations (RenderFlex overflow, unbounded height/width, ParentData misuse). Use when encountering layout exceptions, yellow-black overflow stripes, or red error screens.