Navigation 3 Navigation Graph Patterns
Extension Functions, Sealed NavKeys, and Nested NavDisplay

Navigation 3 no longer uses nested navigation graphs like navigation() in the old Navigation Component.
Instead, you organize screens using one of these three patterns.
1. Group entries with extension functions
Split screen definitions by feature or module.
// AuthModule.kt
fun EntryProviderScope<NavKey>.authGraph() {
entry<Login> { LoginScreen() }
entry<SignUp> { SignUpScreen() }
}
// AppNavigation.kt
val entryProvider = entryProvider {
authGraph()
entry<Home> { HomeScreen() }
}
NavDisplay(
backStack = backStack,
entryProvider = entryProvider
)
This keeps navigation definitions modular while sharing a single NavBackStack.
2. Group NavKeys with sealed interfaces
Organize related destinations under the same namespace.
sealed interface AuthKey : NavKey {
@Serializable
data object Login : AuthKey
@Serializable
data object SignUp : AuthKey
}
sealed interface MainKey : NavKey {
@Serializable
data object Home : MainKey
@Serializable
data class Detail(val id: String) : MainKey
}
Usage is straightforward:
backStack.add(AuthKey.Login)
backStack.add(MainKey.Detail("123"))
This improves readability and keeps your navigation keys organized.
3. Nest NavDisplay for independent back stacks
If a flow needs its own navigation history—such as Bottom Navigation, tabs, or onboarding—create another NavDisplay.
entry<MainTabs> {
MainTabsScreen()
}
@Composable
fun MainTabsScreen() {
val tabBackStack = rememberNavBackStack(HomeTab)
NavDisplay(
backStack = tabBackStack,
entryProvider = entryProvider {
entry<HomeTab> { HomeScreen() }
entry<SearchTab> { SearchScreen() }
entry<ProfileTab> { ProfileScreen() }
}
)
}
Each NavDisplay manages its own NavBackStack, making navigation independent from its parent.
Choosing the right approach
Organize code?
│
├── Yes
│ ├── Extension functions
│ └── Sealed NavKeys
│
└── Need an independent BackStack?
└── Nest NavDisplay
- Use extension functions to split entry definitions by feature.
- Use sealed NavKeys to keep destinations organized and type-safe.
- Use nested NavDisplay only when you need a separate
NavBackStack.
These patterns can be combined, and each solves a different problem.