Navigation3

new-silvermoon/awesome-android-agent-skills/.github/skills/ui/compose-navigation

by new-silvermoon82900eacc8dbe13de93c6310af27b9df4b2bd2f6No licenseListed Oct 9, 2026Updated Oct 9, 2026

Implement navigation in Jetpack Compose using Navigation 3. Use when asked to build state-driven navigation, manage back stacks, scope ViewModels, implement adaptive layouts, or migrate from Navigation Compose.

Instructions onlySoftware Development
AI-generated overview

Guides implementing state-driven navigation in Jetpack Compose apps using Android's Navigation 3 library.

What it does
This skill provides reference guidance for building navigation in Jetpack Compose with Navigation 3, where navigation is modeled as observable application state instead of a NavController. It covers defining serializable navigation keys, managing a mutable back stack, wiring NavDisplay, scoping ViewModels with entry decorators, adaptive layouts, deep links, animations, state restoration, and testing. It also includes a migration table from Navigation Compose to Navigation 3 and recommended project structure.
When to use it
Use it when building or refactoring Android Jetpack Compose navigation with Navigation 3, including state-driven navigation, back stack handling, ViewModel scoping, adaptive layouts, or migration from Navigation Compose. It is also relevant for deep links, transitions, state restoration, and navigation testing in that stack.
Requirements
Requires an Android Jetpack Compose project using Navigation 3, with dependencies such as androidx.navigation3 runtime and UI, lifecycle ViewModel integration, and kotlinx-serialization, plus the Kotlin serialization plugin. It ships no scripts; it is instructions only.

Navigation 3

Overview

Implement state-driven navigation in Jetpack Compose using Navigation 3. Unlike Navigation Compose, Navigation 3 models navigation as application state rather than through a NavController. This skill covers navigation keys, back stack management, ViewModel scoping, entry decorators, adaptive layouts, deep links, animations, state restoration, and testing.

Setup

Add the Navigation 3 dependencies:

kotlin
// build.gradle.ktsdependencies {
    implementation("androidx.navigation3:navigation3-runtime:1.0.0-alpha08")    implementation("androidx.navigation3:navigation3-ui:1.0.0-alpha08")
    // Lifecycle integration    implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:2.9.2")
    // Serialization    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")}
// Enable serialization pluginplugins {    kotlin("plugin.serialization") version "2.2.0"}

Core Concepts

1. Define Navigation Keys

Navigation destinations are represented by immutable serializable objects.

kotlin
import kotlinx.serialization.Serializable
@Serializabledata object Home
@Serializabledata class Profile(    val userId: String)
@Serializabledata class Product(    val productId: String,    val showReviews: Boolean = false)
@Serializabledata object Settings

Keys become your navigation state.


2. Create the Back Stack

Navigation 3 replaces NavController with a mutable state back stack.

kotlin
@Composablefun MyApp() {
    val backStack = remember {        mutableStateListOf<Any>(Home)    }
    AppNavDisplay(backStack)}

3. Create NavDisplay

kotlin
@Composablefun AppNavDisplay(    backStack: SnapshotStateList<Any>) {
    NavDisplay(        backStack = backStack,        onBack = {            if (backStack.size > 1) {                backStack.removeLast()            }        }    ) { key ->
        when (key) {
            Home ->                HomeScreen(                    onProfileClick = {                        backStack += Profile(it)                    }                )
            is Profile ->                ProfileScreen(                    userId = key.userId                )
            is Product ->                ProductScreen(                    productId = key.productId,                    showReviews = key.showReviews                )
            Settings ->                SettingsScreen()        }    }}

Navigation Patterns

Navigate Forward

kotlin
backStack += Profile("user123")

Navigate Back

kotlin
backStack.removeLast()

Replace Current Screen

kotlin
backStack[backStack.lastIndex] = Home

Clear Back Stack

kotlin
backStack.clear()backStack += Home

Pop To Root

kotlin
while (backStack.size > 1) {    backStack.removeLast()}

Argument Handling

Retrieve Arguments

Arguments already exist inside the navigation key.

kotlin
when (val key = currentKey) {
    is Profile -> {        ProfileScreen(            userId = key.userId        )    }
    is Product -> {        ProductScreen(            productId = key.productId        )    }}

Pass IDs, Not Objects

kotlin
// CORRECTbackStack += Profile(user.id)
// Fetch object inside ViewModelclass ProfileViewModel(    savedStateHandle: SavedStateHandle,    repository: UserRepository) : ViewModel() {
    val profile = savedStateHandle.toRoute<Profile>()
    val user =        repository.getUser(profile.userId)}
kotlin
// INCORRECT
backStack += User(...)backStack += ProductRepository(...)backStack += ProductViewModel(...)

ViewModel Integration

Navigation 3 scopes ViewModels using entry decorators.

kotlin
NavDisplay(
    backStack = backStack,
    entryDecorators = listOf(
        rememberSceneSetupNavEntryDecorator(),
        rememberSavedStateNavEntryDecorator(),
        rememberViewModelStoreNavEntryDecorator()    )
) { key ->
    // destinations}

ViewModel Example

kotlin
class ProfileViewModel(    savedStateHandle: SavedStateHandle) : ViewModel() {
    val profile =        savedStateHandle.toRoute<Profile>()}

Entry Decorators

Navigation 3 uses decorators to attach lifecycle functionality.

Scene Setup

kotlin
rememberSceneSetupNavEntryDecorator()

Creates the navigation scene for each entry.

Saved State

kotlin
rememberSavedStateNavEntryDecorator()

Automatically restores destination state after process recreation.

ViewModel Store

kotlin
rememberViewModelStoreNavEntryDecorator()

Scopes ViewModels to each navigation entry.


Adaptive Navigation

Navigation 3 integrates with Material Adaptive layouts.

kotlin
NavDisplay(
    backStack = backStack,
    sceneStrategy = rememberListDetailSceneStrategy()
)

Use adaptive scene strategies to automatically switch between:

  • Single pane (phones)
  • Two pane (tablets)
  • Foldables

Deep Links

Deep links should resolve into navigation keys.

kotlin
fun handleDeepLink(uri: Uri) {
    val userId =        uri.lastPathSegment ?: return
    backStack += Profile(userId)}

Avoid manually constructing route strings.


Animations

Navigation transitions are defined using scene transitions.

kotlin
NavDisplay(
    backStack = backStack,
    transitionSpec = {
        fadeIn() togetherWith fadeOut()
    })

Navigation 3 animation APIs may evolve while in alpha.


State Restoration

Navigation keys are serializable and automatically restored.

kotlin
val backStack = rememberSaveable(    saver = navBackStackSaver()) {    mutableStateListOf(Home)}

Always ensure keys are serializable.


Testing

Navigation becomes simple because it is state-driven.

Example

kotlin
@Testfun navigateToProfile() {
    val backStack =        mutableStateListOf<Any>(Home)
    backStack += Profile("123")
    assertEquals(        Profile("123"),        backStack.last()    )}

Compose UI tests can verify screen rendering by inspecting the current back stack.


Migration from Navigation Compose

Navigation ComposeNavigation 3
NavControllerMutable back stack
NavHostNavDisplay
navigate()backStack += Key
popBackStack()removeLast()
String routesSerializable keys
composable()when(key)
Navigation graphState-driven destinations

Recommended Project Structure

navigation/
    AppNavigation.kt
    NavigationKeys.kt
    NavigationDisplay.kt
feature/
    home/
    profile/
    settings/

Critical Rules

DO

  • Use immutable serializable keys
  • Keep navigation state inside Compose
  • Pass IDs instead of complex objects
  • Scope ViewModels using entry decorators
  • Use rememberSaveable for state restoration
  • Model navigation as observable application state

DON'T

  • Use string routes
  • Pass repositories or ViewModels through navigation
  • Mutate navigation keys
  • Store business objects in the back stack
  • Recreate the back stack on recomposition
  • Mix Navigation Compose APIs with Navigation 3 APIs

References

  • Android Navigation 3 documentation
  • Navigation 3 samples
  • Lifecycle ViewModel Navigation 3 documentation
  • Material 3 Adaptive Navigation documentation

Source and attribution

Source:new-silvermoon/awesome-android-agent-skillsin.github/skills/ui/compose-navigationat commit82900ea

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal