{"id":34882026,"url":"https://github.com/serbelga/navigation-compose-extended","last_synced_at":"2026-02-01T15:03:49.161Z","repository":{"id":227847836,"uuid":"609999584","full_name":"serbelga/navigation-compose-extended","owner":"serbelga","description":"🧭 A Kotlin Multiplatform library for Jetpack Navigation Compose to improve creation of navigation elements in a more idiomatic way","archived":false,"fork":false,"pushed_at":"2026-01-28T08:05:57.000Z","size":814,"stargazers_count":10,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-28T23:04:07.431Z","etag":null,"topics":["annotation-processor","annotations","compose","jetpack","kotlinpoet","ksp","multiplatform","navigation","safe-nav-args"],"latest_commit_sha":null,"homepage":"http://sergiobelda.dev/navigation-compose-extended/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/serbelga.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-05T21:11:28.000Z","updated_at":"2026-01-28T08:06:01.000Z","dependencies_parsed_at":"2024-05-21T02:57:15.632Z","dependency_job_id":"0ad2da2d-0084-4a4b-a6db-4a2a00d7f355","html_url":"https://github.com/serbelga/navigation-compose-extended","commit_stats":null,"previous_names":["serbelga/navigation-compose-extension","serbelga/navigation-compose-extended"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/serbelga/navigation-compose-extended","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serbelga%2Fnavigation-compose-extended","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serbelga%2Fnavigation-compose-extended/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serbelga%2Fnavigation-compose-extended/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serbelga%2Fnavigation-compose-extended/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/serbelga","download_url":"https://codeload.github.com/serbelga/navigation-compose-extended/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serbelga%2Fnavigation-compose-extended/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28980855,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T13:38:33.235Z","status":"ssl_error","status_checked_at":"2026-02-01T13:38:32.912Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation-processor","annotations","compose","jetpack","kotlinpoet","ksp","multiplatform","navigation","safe-nav-args"],"created_at":"2025-12-26T02:18:49.657Z","updated_at":"2026-02-01T15:03:49.148Z","avatar_url":"https://github.com/serbelga.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Navigation Compose Extended\n\n[![Maven Central](https://img.shields.io/maven-central/v/dev.sergiobelda.navigation.compose.extended/navigation-compose-extended)](https://search.maven.org/search?q=g:dev.sergiobelda.navigation.compose.extended)\n\nNavigation Compose Extended is a complementary multiplatform library for Jetpack Navigation Compose to\nimprove creation of navigation elements, as destination routes, arguments, deep links, … in a\nmore idiomatic way than using literals. It also provides Safe navigation routes and Safe navigation arguments.\n\nTake a look at the [sample-app-annotations](https://github.com/serbelga/navigation-compose-extended/tree/main/sample-app-annotations) and [sample-app](https://github.com/serbelga/navigation-compose-extended/tree/main/sample-app) for working examples.\n\nVisit the [project website](https://sergiobelda.dev/navigation-compose-extended/) for documentation and API Reference.\n\n## Download\n\n\u003cdetails\u003e\n\n\u003csummary\u003eAndroid only\u003c/summary\u003e\n\n```kotlin\n// Optional: Use Annotations to generate NavDestinations.\nplugins {\n    id(\"com.google.devtools.ksp\")\n}\n\ndependencies {\n    // Add AndroidX Navigation Compose dependency.\n    implementation(\"androidx.navigation:navigation-compose:$nav_version\")\n\n    implementation(\"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended:$version\") \n    \n    // Optional: Use Annotations to generate NavDestinations.\n    implementation(\"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended-annotation:$version\")\n    ksp(\"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended-compiler:$version\")\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eMultiplatform\u003c/summary\u003e\n\n```kotlin\n// Optional: Use Annotations to generate NavDestinations.\nplugins {\n    id(\"com.google.devtools.ksp\")\n}\n\nkotlin {\n\n    sourceSets {\n        commonMain.dependencies {\n            // Add Jetbrains Navigation Compose Multiplatform dependency.\n            implementation(\"org.jetbrains.androidx.navigation:navigation-compose:$jetbrains_nav_version\")\n\n            implementation(\"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended:$version\")\n            // Optional: Use Annotations to generate NavDestinations.\n            implementation(\"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended-annotation:$version\")\n        }\n    }\n}\n\n// If use Annotations, add compiler dependency.\ndependencies {\n    add(\"kspCommonMainMetadata\", \"dev.sergiobelda.navigation.compose.extended:navigation-compose-extended-compiler:$version\")\n}\n\n// Workaround for KSP only in Common Main.\n// https://github.com/google/ksp/issues/567\ntasks.withType\u003corg.jetbrains.kotlin.gradle.dsl.KotlinCompile\u003c*\u003e\u003e().all {\n    if (name != \"kspCommonMainKotlinMetadata\") {\n        dependsOn(\"kspCommonMainKotlinMetadata\")\n    }\n}\n\nkotlin.sourceSets.commonMain {\n    kotlin.srcDir(\"build/generated/ksp/metadata/commonMain/kotlin\")\n}\n```\n\n\u003c/details\u003e\n\n## Usage\n\n\u003e [!IMPORTANT]  \n\u003e In the next documentation, annotations are used to create navigation elements, but we can also create them programmatically.\n\nThe `NavDestination` represents some Destination in the Navigation graph.\n\n### Create a NavDestination\n\n```kotlin\n@NavDestination(\n    destinationId = \"home\",\n    name = \"Home\", // Optional: NavDestination name.\n    isTopLevelNavDestination = true, // Optional: Mark NavDestination as a top-level destination.\n)\n@Composable\nfun HomeScreen() {}\n```\n\nThe compiler will generate a `NavDestination` object associated with this destination.\n\n```kotlin\npublic object HomeNavDestination : NavDestination\u003cHomeNavArgumentKeys\u003e() {\n  override val destinationId: String = \"home\"\n}\n```\n\n### Using the NavDestination into the NavHost\n\n```kotlin\nNavHost(navController = navController, startNavDestination = HomeNavDestination) {\n    composable(navDestination = HomeNavDestination) {\n        HomeScreen()\n    }\n    composable(navDestination = SettingsNavDestination) {\n        SettingsScreen()\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e Here we are using wrappers (`NavHost`, `composable`) that receive the `NavDestination` type to create the navigation graph. \n\u003e Visit the [API Reference](https://sergiobelda.dev/navigation-compose-extended/api/navigation-compose-extended/dev.sergiobelda.navigation.compose.extended/index.html) for \n\u003e more information.\n\n`NavDestination` base class also offers `route`, `arguments` and `deepLinks` getters that can be used as follows if we don't want to use these wrappers:\n\n```kotlin\nNavHost(navController = navController, startDestination = HomeNavDestination.route) {\n    composable(\n        route = HomeNavDestination.route,\n        deepLinks = HomeNavDestination.deepLinks\n    ) {\n        HomeScreen()\n    }\n    composable(\n        route = SettingsNavDestination.route,\n        arguments = SettingsNavDestination.arguments\n    ) {\n        SettingsScreen()\n    }\n}\n```\n\n### Navigate\n\nWe can navigate to some destination using the actions functions provided by the `NavAction` class.\nThe `NavAction.navigate()` function receive a `NavRoute` instance to navigate to some destination.\nThis `NavRoute` associated with a destination can be obtained using the `navRoute()` function in the `NavDestination` class or\nthe `safeNavRoute()` function if we are using annotations.\nIn the following code, we navigate to the `SettingsNavDestination`:\n\n```kotlin\nval navAction = rememberNavAction(navController)\nNavHost(navController = navController, startNavDestination = HomeNavDestination) {\n    composable(navDestination = HomeNavDestination) {\n        HomeScreen(\n            navigateToSettings = {\n                navAction.navigate(\n                    SettingsNavDestination.navRoute()\n                )\n            },\n        )\n    }\n```\n\n### Navigate with arguments\n\nIf we are using annotations, we can use the `arguments` parameter in `@NavDestination` annotation:\n\n```kotlin\n@NavDestination(\n    name = \"Settings\",\n    destinationId = \"settings\",\n    arguments = [\n        NavArgument(name = \"userId\", type = NavArgumentType.Int),\n        NavArgument(name = \"text\", type = NavArgumentType.String, defaultValue = \"Default\"),\n        NavArgument(name = \"result\", type = NavArgumentType.Boolean, defaultValue = \"true\"),\n    ],\n)\n@Composable\nfun SettingsScreen(\n    viewModel: SettingsViewModel\n) {}\n```\n\nThe compiler will generate an enum class containing the navigation arguments keys for this navigation destination. The `NavArgumentKey` represents the navigation argument's key.\n\n```kotlin\npublic enum class SettingsNavArgumentKeys(\n  override val argumentKey: String,\n) : NavArgumentKey {\n  UserIdNavArgumentKey(\"userId\"),\n  TextNavArgumentKey(\"text\"),\n  ResultNavArgumentKey(\"result\"),\n  ;\n}\n```\n\nThe compiler also set the `argumentsMap` property in the `NavDestination` that associate each `NavArgumentKey` with its properties.\n\n```kotlin\npublic object SettingsNavDestination : NavDestination\u003cSettingsNavArgumentKeys\u003e() {\n  override val destinationId: String = \"settings\"\n\n  override val argumentsMap: Map\u003cSettingsNavArgumentKeys, NavArgumentBuilder.() -\u003e Unit\u003e = mapOf(\n    SettingsNavArgumentKeys.UserIdNavArgumentKey to {\n      type = NavType.IntType\n    },\n    SettingsNavArgumentKeys.TextNavArgumentKey to {\n      type = NavType.StringType\n      nullable = true\n      defaultValue = \"Default\"\n    },\n    SettingsNavArgumentKeys.ResultNavArgumentKey to {\n      type = NavType.BoolType\n      defaultValue = true\n    },\n  )\n```\n\n\u003e [!NOTE]  \n\u003e If we don't use annotations, we should create this enum class and set the `argumentsMap` programmatically.\n\nIf we use annotations, we can use the generated `safeNavRoute()` function with the navigation arguments as parameters:\n\n```kotlin\ncomposable(navDestination = HomeNavDestination) {\n    HomeScreen(\n        navigateToSettings = {\n            navAction.navigate(\n                SettingsNavDestination.safeNavRoute(\n                    userId = 1,\n                    text = \"Text\",\n                    result = true\n                )\n            )\n        },\n    )\n}\n```\n\notherwise, we must use `navRoute()` function associating the NavArgumentKey to its value.\n\n```kotlin\ncomposable(navDestination = HomeNavDestination) {\n    HomeScreen(\n        navigateToSettings = {\n            navAction.navigate(\n                SettingsNavDestination.navRoute(\n                    SettingsNavArgumentKeys.UserIdNavArgumentKey to 1,\n                    SettingsNavArgumentKeys.TextNavArgumentKey to \"Text\",\n                    SettingsNavArgumentKeys.ResultNavArgumentKey to true\n                )\n            )\n        },\n    )\n}\n```\n\n### Retrieving the navigation arguments values\n\nThe value of navigation arguments can be obtained using the `NavArgs` class. The `NavDestination.navArgs()` provides an instance\nof this class. There are multiple getters to retrieve values:\n\n```kotlin\ncomposable(navDestination = SettingsNavDestination) { navBackStackEntry -\u003e\n    val navArgs = SettingsNavDestination.navArgs(navBackStackEntry)\n    val userId = navArgs.getInt(SettingsNavArgumentKeys.UserIdNavArgumentKey) ?: 0\n    SettingsScreen(\n        userId = userId,\n```\n\nIf we use annotations, a `SafeNavArgs` class is generated with getters for each navigation argument:\n\n```kotlin\ncomposable(navDestination = SettingsNavDestination) { navBackStackEntry -\u003e\n    val navArgs = SettingsSafeNavArgs(navBackStackEntry)\n    SettingsScreen(\n        userId =  navArgs.userId ?: 0,\n```\n\n## Navigate with Deep Links\n\nIn the `AndroidManifest.xml`:\n\n```xml\n\u003cactivity\n    ...\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.VIEW\" /\u003e\n        \u003ccategory android:name=\"android.intent.category.DEFAULT\" /\u003e\n        \u003ccategory android:name=\"android.intent.category.BROWSABLE\" /\u003e\n        \u003cdata android:scheme=\"sample\" android:host=\"home\" /\u003e\n    \u003c/intent-filter\u003e\n\u003c/activity\u003e\n```\n\nIf we are defining the navigation destinations using the `@NavDestination` annotation, we can use the property `deepLinkUris` as follows:\n\n```kotlin\n@NavDestination(\n    destinationId = \"home\",\n    deepLinkUris = [\n        \"sample://home\",\n    ]\n)\n@Composable\nfun HomeScreen(navigateToSettings: () -\u003e Unit) {}\n```\n\notherwise, we should set the list of deepLink uris in the `NavDestination` object:\n\n```kotlin\nobject HomeNavDestination : NavDestination\u003cHomeNavArgumentKeys\u003e() {\n  override val deepLinkUris: List\u003cString\u003e = listOf(\n    \"sample://home\",\n    \"sample://home_secondary\"\n  )\n```\n\nTrigger the deep link using adb:\n\n```shell\nadb shell am start -a android.intent.action.VIEW -d \"sample://home\"\n```\n\n## License\n\n```\n   Copyright 2024 Sergio Belda\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserbelga%2Fnavigation-compose-extended","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fserbelga%2Fnavigation-compose-extended","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserbelga%2Fnavigation-compose-extended/lists"}