DEV Community

Twilight
Twilight

Posted on

Best Practices for Managing Route Names and Paths with go_router in Flutter

Are you tired of typing out long, hard-coded paths when navigating between screens in your Flutter app? Or worried about circular imports while organizing your routes across multiple features? In this post, we’ll explore how to manage route names and paths using go_router in a clean and maintainable way.


1. Why Avoid Hard-Coding Routes?

Using strings like context.go("/some/really/long/path/42") all over your codebase can be error-prone and difficult to maintain. If you ever decide to change "/some/really/long/path" to "/shorter/path", you’ll have to hunt down every place that calls it.

Instead, define named routes or centralized route constants. This helps you:

  • Avoid typos.
  • Keep the code DRY (Don’t Repeat Yourself).
  • Make future changes to your routes simpler.

2. Named Routes in go_router

go_router lets you define both a path and a name for your routes. You can then call context.goNamed() instead of context.go().

Here’s a quick example:

import 'package:go_router/go_router.dart';

final router = GoRouter(
  routes: [
    GoRoute(
      name: 'home',
      path: '/home',
      builder: (context, state) => const HomePage(),
    ),
    GoRoute(
      name: 'profile',
      path: '/profile/:userId',
      builder: (context, state) {
        final userId = state.pathParameters['userId'];
        return ProfilePage(userId: userId);
      },
    ),
  ],
);

// Navigate by route name
context.goNamed('profile', params: {'userId': '42'});
Enter fullscreen mode Exit fullscreen mode

With named routes:

  • If you rename /profile/:userId to /users/:id, you only update one place (the route definition) instead of every go() call in the project.

3. Centralizing Route Names and Paths

Create a file or class that contains all of your route constants. For example:

// app_routes.dart
abstract class AppRouteName {
  static const home = 'home';
  static const profile = 'profile';
}

abstract class AppRoutePath {
  static const home = '/home';
  static const profile = '/profile/:userId';
}
Enter fullscreen mode Exit fullscreen mode

Then, when defining routes:

GoRoute(
  name: AppRouteName.profile,
  path: AppRoutePath.profile,
  builder: (context, state) => ...
);
Enter fullscreen mode Exit fullscreen mode

And when navigating:

context.goNamed(
  AppRouteName.profile,
  params: {'userId': '42'},
);
Enter fullscreen mode Exit fullscreen mode

This approach makes it easy to manage changes in path structure and ensures a single source of truth for route definitions.


4. Organizing Routes in Larger Apps

If you’re following a feature-first approach:

  1. Core Layer: Defines shared resources, services, or base classes.
  2. Feature Layer: Each feature can define its own UI, logic, and route definitions.
  3. App (Composition) Layer: Imports both the core and the features, then merges all routes in one central GoRouter.

This avoids circular imports:

  • Core doesn’t import features.
  • Features import core if needed.
  • App imports both core and features to assemble the final routes.

A typical folder structure might look like this:

lib/
 ├── core/
 |    └── app_routes.dart
 ├── features/
 |    ├── feature_a/
 |    └── feature_b/
 └── app/
      ├── app_router.dart
      └── main.dart
Enter fullscreen mode Exit fullscreen mode

The app_router.dart then gathers routes from core and each feature, creating one unified router.


5. Final Tips

  • Use go_router_builder if you want generated, type-safe route navigation functions like context.goToProfile(userId: 42).
  • Keep route definitions minimal and avoid burying complex logic within them.
  • For dynamic screens, leverage pathParameters or queryParameters to parse IDs and flags.

By following these best practices—named routes, centralized constants, and a layered architecture—you’ll save yourself tons of headaches and ensure a more maintainable Flutter codebase. Happy coding!

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay