Annotation processing library for type-safe Jetpack Compose navigation with no boilerplate.
3,389
stars
702
commits
Kotlin
primary language
Oct 12, 2025
updated
A KSP library that processes annotations and generates code that uses Official Jetpack Compose Navigation under the hood. It hides the complex, non-type-safe and boilerplate code you would have to write otherwise.
No need to learn a whole new framework to navigate - most APIs are either the same as with the Jetpack Components or inspired by them.
Please consider migrating to it and leaving feedback as GH issue or on our slack channel #compose-destinations!
SavedStateHandle (useful in ViewModels) and NavBackStackEntry in a type-safe way.For a deeper look into all the features, check our documentation website.
[!NOTE]
This readme is about v2. If you're now starting to use Compose Destinations, I strongly recommend using v2. If you really want to see basic v1 usage, check it here.
@Destination<RootGraph>:@Destination<RootGraph> // sets this as a destination of the "root" nav graph
@Composable
fun ProfileScreen() { /*...*/ }
@Destination<RootGraph>
@Composable
fun ProfileScreen(
id: Int, // <-- required navigation argument
groupName: String?, // <-- optional navigation argument
isOwnUser: Boolean = false // <-- optional navigation argument
) { /*...*/ }
Parcelable, Serializable, Enum and classes annotated with @kotlinx.serialization.Serializable (as well as Arrays and ArrayLists of these) work out of the box!
You can also make any other type a navigation argument type. Read about it here
[!TIP]
There is an alternative way to define the destination arguments in case you don't need to use them inside the Composable (as is likely the case when using ViewModel). Read more here.
Or run ksp task (example: ./gradlew kspDebugKotlin), to generate all the Destinations. With the above annotated composable, a ProfileScreenDestination file would be generated (that we'll use in step 4).
[ComposableName]Destination's invoke method to navigate to it.It will have the correct typed arguments.
@Destination<RootGraph>(start = true) // sets this as the start destination of the "root" nav graph
@Composable
fun HomeScreen(
navigator: DestinationsNavigator
) {
/*...*/
navigator.navigate(ProfileScreenDestination(id = 7, groupName = "Kotlin programmers"))
}
DestinationsNavHost(navGraph = NavGraphs.root)
[!NOTE]
NavGraphsis a generated file that contains all navigation graphs.roothere corresponds to the<RootGraph>we used in the above examples. You're also able to define your own navigation graphs to use instead of<RootGraph>.
This call adds all annotated Composable functions as destinations of the Navigation Host.
That's it! No need to worry about routes, NavType, bundles and strings. All that redundant and
error-prone code gets generated for you.
Compose destinations is available via maven central.
Note: The version you chose for the KSP plugin depends on the Kotlin version your project uses.
You can check https://github.com/google/ksp/releases for the list of KSP versions, then pick the last release that matches your Kotlin version. Example: If you're using1.9.22Kotlin version, then the last KSP version is1.9.22-1.0.17.
plugins {
//...
id 'com.google.devtools.ksp' version '1.9.22-1.0.17' // Depends on your kotlin version
}
plugins {
//...
id("com.google.devtools.ksp") version "1.9.22-1.0.17" // Depends on your kotlin version
}
Compose Destinations has multiple active versions. The higher one uses the latest versions for Compose and Navigation, while the others use only stable versions. Choose the one that matches your Compose version, considering this table:
| Compose 1.1 (1.1.x) | |
| Compose 1.2 (1.2.x) | |
| Compose 1.3 (1.3.x) | |
| Compose 1.4 (1.4.x) | |
| Compose 1.5 (1.5.x) | |
| Compose 1.6 (1.6.x) |
|
| Compose 1.7 (1.7.x) |
|
| Compose 1.8 (1.8.x) |
|
| Compose 1.9 (1.9.x) |
|
[!WARNING]
If you choose a version that uses a higher version of Compose than the one you're setting for your app, gradle will upgrade your Compose version via transitive dependency.
implementation 'io.github.raamcosta.compose-destinations:core:<version>'
ksp 'io.github.raamcosta.compose-destinations:ksp:<version>'
// V2 only: for bottom sheet destination support, also add
implementation 'io.github.raamcosta.compose-destinations:bottom-sheet:<version>'
implementation("io.github.raamcosta.compose-destinations:core:<version>")
ksp("io.github.raamcosta.compose-destinations:ksp:<version>")
// V2 only: for bottom sheet destination support, also add
implementation("io.github.raamcosta.compose-destinations:bottom-sheet:<version>")
[!NOTE]
If you want to use Compose Destinations in a Wear OS app, replace above core dependency with:
implementation 'io.github.raamcosta.compose-destinations:wear-core:<version>'
this will use Wear Compose Navigation internally.
Read more about the next steps to configure these features here
1.11.3-alpha / 2.1.0-beta02 and above (Compose 1.7)OR if you got this error kotlinx.serialization.SerializationException: Serializer for class 'DirectionImpl' is not found.
NavController.navigate function anywhereWith the introduction of type safe APIs on the official library, our NavController extension functions that received Direction are now shadowed by new member functions on NavController.
This means that the official member function would be called instead of our extension functions, and so we removed those extension functions.
Instead, always make sure to use DestinationsNavigator. You can get one of such navigators by:
DestinationsNavigator instead of NavController in your annotated screens.DestinationsNavHost, bottom nav bar, etc)
navController.rememberDestinationsNavigator() if in a ComposablenavController.toDestinationsNavigator() if not in a ComposableRead more about these changes here.
Compose Destinations provides the correct version transitively.
So, if you have dependency on androidx.navigation:navigation-compose, please remove it! This has always been true, but more important now.
Please join the community at Kotlin slack channel: #compose-destinations
Ask questions, suggest improvements, or anything else related to the library.
If you like the library, consider starring and sharing it with your colleagues.
Kotlin
99.3%
Annotation processing library for type-safe Jetpack Compose navigation with no boilerplate.
3,389
stars
702
commits
Kotlin
primary language
Oct 12, 2025
updated
A KSP library that processes annotations and generates code that uses Official Jetpack Compose Navigation under the hood. It hides the complex, non-type-safe and boilerplate code you would have to write otherwise.
No need to learn a whole new framework to navigate - most APIs are either the same as with the Jetpack Components or inspired by them.
Please consider migrating to it and leaving feedback as GH issue or on our slack channel #compose-destinations!
SavedStateHandle (useful in ViewModels) and NavBackStackEntry in a type-safe way.For a deeper look into all the features, check our documentation website.
[!NOTE]
This readme is about v2. If you're now starting to use Compose Destinations, I strongly recommend using v2. If you really want to see basic v1 usage, check it here.
@Destination<RootGraph>:@Destination<RootGraph> // sets this as a destination of the "root" nav graph
@Composable
fun ProfileScreen() { /*...*/ }
@Destination<RootGraph>
@Composable
fun ProfileScreen(
id: Int, // <-- required navigation argument
groupName: String?, // <-- optional navigation argument
isOwnUser: Boolean = false // <-- optional navigation argument
) { /*...*/ }
Parcelable, Serializable, Enum and classes annotated with @kotlinx.serialization.Serializable (as well as Arrays and ArrayLists of these) work out of the box!
You can also make any other type a navigation argument type. Read about it here
[!TIP]
There is an alternative way to define the destination arguments in case you don't need to use them inside the Composable (as is likely the case when using ViewModel). Read more here.
Or run ksp task (example: ./gradlew kspDebugKotlin), to generate all the Destinations. With the above annotated composable, a ProfileScreenDestination file would be generated (that we'll use in step 4).
[ComposableName]Destination's invoke method to navigate to it.It will have the correct typed arguments.
@Destination<RootGraph>(start = true) // sets this as the start destination of the "root" nav graph
@Composable
fun HomeScreen(
navigator: DestinationsNavigator
) {
/*...*/
navigator.navigate(ProfileScreenDestination(id = 7, groupName = "Kotlin programmers"))
}
DestinationsNavHost(navGraph = NavGraphs.root)
[!NOTE]
NavGraphsis a generated file that contains all navigation graphs.roothere corresponds to the<RootGraph>we used in the above examples. You're also able to define your own navigation graphs to use instead of<RootGraph>.
This call adds all annotated Composable functions as destinations of the Navigation Host.
That's it! No need to worry about routes, NavType, bundles and strings. All that redundant and
error-prone code gets generated for you.
Compose destinations is available via maven central.
Note: The version you chose for the KSP plugin depends on the Kotlin version your project uses.
You can check https://github.com/google/ksp/releases for the list of KSP versions, then pick the last release that matches your Kotlin version. Example: If you're using1.9.22Kotlin version, then the last KSP version is1.9.22-1.0.17.
plugins {
//...
id 'com.google.devtools.ksp' version '1.9.22-1.0.17' // Depends on your kotlin version
}
plugins {
//...
id("com.google.devtools.ksp") version "1.9.22-1.0.17" // Depends on your kotlin version
}
Compose Destinations has multiple active versions. The higher one uses the latest versions for Compose and Navigation, while the others use only stable versions. Choose the one that matches your Compose version, considering this table:
| Compose 1.1 (1.1.x) | |
| Compose 1.2 (1.2.x) | |
| Compose 1.3 (1.3.x) | |
| Compose 1.4 (1.4.x) | |
| Compose 1.5 (1.5.x) | |
| Compose 1.6 (1.6.x) |
|
| Compose 1.7 (1.7.x) |
|
| Compose 1.8 (1.8.x) |
|
| Compose 1.9 (1.9.x) |
|
[!WARNING]
If you choose a version that uses a higher version of Compose than the one you're setting for your app, gradle will upgrade your Compose version via transitive dependency.
implementation 'io.github.raamcosta.compose-destinations:core:<version>'
ksp 'io.github.raamcosta.compose-destinations:ksp:<version>'
// V2 only: for bottom sheet destination support, also add
implementation 'io.github.raamcosta.compose-destinations:bottom-sheet:<version>'
implementation("io.github.raamcosta.compose-destinations:core:<version>")
ksp("io.github.raamcosta.compose-destinations:ksp:<version>")
// V2 only: for bottom sheet destination support, also add
implementation("io.github.raamcosta.compose-destinations:bottom-sheet:<version>")
[!NOTE]
If you want to use Compose Destinations in a Wear OS app, replace above core dependency with:
implementation 'io.github.raamcosta.compose-destinations:wear-core:<version>'
this will use Wear Compose Navigation internally.
Read more about the next steps to configure these features here
1.11.3-alpha / 2.1.0-beta02 and above (Compose 1.7)OR if you got this error kotlinx.serialization.SerializationException: Serializer for class 'DirectionImpl' is not found.
NavController.navigate function anywhereWith the introduction of type safe APIs on the official library, our NavController extension functions that received Direction are now shadowed by new member functions on NavController.
This means that the official member function would be called instead of our extension functions, and so we removed those extension functions.
Instead, always make sure to use DestinationsNavigator. You can get one of such navigators by:
DestinationsNavigator instead of NavController in your annotated screens.DestinationsNavHost, bottom nav bar, etc)
navController.rememberDestinationsNavigator() if in a ComposablenavController.toDestinationsNavigator() if not in a ComposableRead more about these changes here.
Compose Destinations provides the correct version transitively.
So, if you have dependency on androidx.navigation:navigation-compose, please remove it! This has always been true, but more important now.
Please join the community at Kotlin slack channel: #compose-destinations
Ask questions, suggest improvements, or anything else related to the library.
If you like the library, consider starring and sharing it with your colleagues.
Kotlin
99.3%