| j / k | Scroll down / up |
| gg | Scroll to top |
| G | Scroll to bottom |
| ⌘K / / | Open search |
| ? | Show this help |
| Esc | Close search / help |
| n / N | Next / previous section |
| h | Go to landing |
| d | Go to docs |
| : | Command mode — type section name |
Press ? or Esc to close
Every feature is a self-contained vertical slice. The only thing the outside world imports is the feature's config/ folder — its route and DI module.
One function per feature, called from bootstrap(). Singletons are lazy (created on first access); Cubits are factories (a fresh instance per screen).
void registerProfileDependencies() {
// Shared instance, created on first access
sl.registerLazySingleton(() => ProfileDataSource(sl<ApiClient>()));
sl.registerLazySingleton(() => ProfileStore(sl<ProfileDataSource>()));
// Fresh instance each time the screen is opened
sl.registerFactory(() => ProfileCubit(sl<ProfileStore>()));
} The feature owns its GoRoute. The app collects them all. Full-screen sub-routes (e.g. detail pages) set parentNavigatorKey so they push above the shell.
final profileRoute = GoRoute(
path: AppRoutes.profile.route,
name: AppRoutes.profile.name,
builder: (context, state) => const ProfileScreen(),
routes: [
GoRoute(
path: AppRoutes.profileView.route,
parentNavigatorKey: rootNavigatorKey,
builder: (context, state) => ProfileViewScreen(
userId: state.pathParameters['id']!,
),
),
],
);