{"id":40663329,"url":"https://github.com/nxoim/decomposite","last_synced_at":"2026-01-21T09:04:31.661Z","repository":{"id":221111429,"uuid":"753475897","full_name":"nxoim/decomposite","owner":"nxoim","description":"Router style navigation library with Decompose used as a base with some features on top, like view model store, overlays, snack bars, custom extensions like animations, etc.","archived":false,"fork":false,"pushed_at":"2024-03-28T10:54:27.000Z","size":61679,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T01:11:25.611Z","etag":null,"topics":["compose-multiplatform","jetpack-compose","kotlin","kotlin-multiplatform","library","navigation"],"latest_commit_sha":null,"homepage":"","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/nxoim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.MD","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}},"created_at":"2024-02-06T07:41:46.000Z","updated_at":"2024-04-15T06:21:38.752Z","dependencies_parsed_at":"2024-03-28T12:06:42.066Z","dependency_job_id":null,"html_url":"https://github.com/nxoim/decomposite","commit_stats":null,"previous_names":["number869/decomposite"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/nxoim/decomposite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nxoim%2Fdecomposite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nxoim%2Fdecomposite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nxoim%2Fdecomposite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nxoim%2Fdecomposite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nxoim","download_url":"https://codeload.github.com/nxoim/decomposite/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nxoim%2Fdecomposite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28630938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"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":["compose-multiplatform","jetpack-compose","kotlin","kotlin-multiplatform","library","navigation"],"created_at":"2026-01-21T09:04:30.995Z","updated_at":"2026-01-21T09:04:31.652Z","avatar_url":"https://github.com/nxoim.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![](https://jitpack.io/v/nxoim/decomposite.svg)](https://jitpack.io/#nxoim/decomposite)\n\n![badge-Android](https://img.shields.io/badge/Platform-Android-brightgreen)\n![badge-JVM](https://img.shields.io/badge/Platform-JVM-orange)\n![badge-iOS](https://img.shields.io/badge/Platform-iOS-lightgray)(?)\n![badge-macOS](https://img.shields.io/badge/Platform-macOS-purple)(?)\n(i dont have apple's devices) Some time in the future WASM/JS and maybe WASI.\n\n# What?\nRouter style navigation library with Decompose used as a base with some features on top, like view model store, overlays, custom extensions like animations, etc.\n\n# Why?\nThere was existing multiplatform tooling, but it was kinda raw for my taste, so I started learning and experimenting by making DSLs based on it and this is the result.\n\n# ... What was the thought process?\nUhm...\n\n# Here's what it has and can do\n- Convenient type-safe router-style navigation\n- Custom animation system (inspired by Decompose)\n- Properly store view models, with configuration change handling, view model scope cancellation and allat\n- Convenient view model instance creation\n- Display destinations in overlays\n- Pass the backstack entry's component context using CompositionLocalProvider\n- Pass the type (contained/overlay) of the displayed content also using CompositionLocalProvider \n- Store navigation controller instances like view models\n- Automatically create navigation controller instances upon the creation of nav hosts that are retrievable by just calling navController, again, kind of like view models\n\n# Examples/Getting Started\nIn your version catalog add the \"com.github.nxoim.decomposite:decomposite\" artifact. In your toml file that would be:\n```\ndecomposite = { module = \"com.github.nxoim.decomposite:decomposite\", version.ref = \"version\" }\n```\n\nFirst you have to set up the app by creating a root of the app. This root sets up stores for view models and nav controllers, overlay stuff, and provides the root component context.\n\nOn Android:\n```kotlin\nclass YourActivity : ComponentActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n    \tsuper.onCreate(savedInstanceState)\n\n        // default component context is included with the decompose library\n        val navigationRootData = NavigationRootData(defaultComponentContext())\n\n        setContent {\n            NavigationRootProvider(navigationRootData) { YourContent() }\n        }\n    }\n}\n```\n\nCheck out [the android sample](https://github.com/nxoim/decomposite/blob/update/sample/app/src/androidMain/kotlin/com/nxoim/decomposite/App.android.kt) if you want predictive gesture animations application-wide and on older androids. \n\nOn everything else:\n```kotlin\n// outside compose\nval navigationRootData = NavigationRootData()\n\n// ...\n\n// inside any composable at the root\nNavigationRootProvider(navigationRootData) { YourContent() }\n```\n\nNavigation host creation:\n```kotlin\n// creating an instance\nval yourNavController = navController\u003cYourDestinations\u003e(startingDestination = YourDestinations.Star)\n\nScaffold(\n    bottomBar = { \n\t\tGlobalSampleNavBar(onBack = { yourNavController.navigateBack() }) \n\t}\n) { scaffoldPadding -\u003e\n    NavHost(\n        yourNavController,\n        Modifier.padding(scaffoldPadding),        \n        animations = {\n            when (currentChild) {\n                RootDestinations.Star -\u003e fade() + scale()\n                else -\u003e cleanSlideAndFade()\n            }\n        }\n    ) {\n        when (it) { // nested hosts!\n            RootDestinations.Star -\u003e StarNavHost()\n            RootDestinations.Heart -\u003e HeartNavHost()\n        }\n    }    \n}\n```\n\nNavigation controller usage:\n```kotlin\n// in any clickable\nyourNavController.navigate(YourDestinations.Heart)\n\n// navigate back\nyourNavController.navigateBack()\n```\n\nView model creation and usage:\n```kotlin\n@Composable\nfun YourScreen() {\n    // get or create a view model\n    val vm = viewModel(\"optional key\") { SomeViewModel(someArgument = \"some text\") }\n\n    // just get a view model. \n    val vm = getExistingViewModel\u003cSomeViewModel\u003e(\"optional key\")\n}\n\nclass SomeViewModel(someArgument: String) : ViewModel() {\n    // you can retain the view model until the app gets destroyed by overriding \n    // onDestroy and not calling removeFromViewModelStore\n    override fun onDestroy(removeFromViewModelStore: () -\u003e Unit) {\n        // maybe still cancel the scope? maybe\n        viewModelScope.coroutineContext.cancelChildren()\n    }\n}\n```\n\nBack gestures on other platforms:\n```kotlin\n// this is for jvm\n@OptIn(ExperimentalDecomposeApi::class)\nfun main() = application {\n        // initialize this at the root of your app\n        val navigationRootData = NavigationRootData()\n\n        Window(\n            title = \"Decomposite\",\n            onCloseRequest = ::exitApplication,\n        ) {\n            window.minimumSize = Dimension(350, 600)\n\n            SampleTheme {\n                // first wrap your app in a theme.\n                // because of material 3 quirks - surface wraps the root to fix text\n                // colors in overlays.\n                Surface {\n                    // also since you need to initialize the component context of the app\n                    // on your preferred platform anyway - it's ok to add decomposite to\n                    // your entry-point/app module of the project, or combine it with your\n                    // navigation module\n\n                    // then initialize the back gesture overlay that will handle the back gestures.\n                    // initialize it first, put NavigationRoot inside it, else overlays will not\n                    // detect the gestures\n                    BackGestureProviderContainer(\n                        navigationRootData.defaultComponentContext,\n                        content = { NavigationRootProvider(navigationRootData) { App() } }\n                    )\n                }\n            }\n        }\n    }\n```\n\nOr you can apply a modifier to the content you want to handle the back gestures, like:\n```kotlin\nExampleComposable(Modifier.backGestureProvider(LocalBackDispatcher.current))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnxoim%2Fdecomposite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnxoim%2Fdecomposite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnxoim%2Fdecomposite/lists"}