
Library enhances navigation in compose-based applications with multi-layer navigation, authentication, responsive design, state restoration, and feature toggles, supporting device-aware and type-safe routing.
A Kotlin Multiplatform routing library with advanced features for managing navigation in compose-based applications.
dependencies {
implementation("io.crowded-innovations:duks-routing:0.1.4")
}// Define your app state
@Serializable
data class AppState(
val user: User? = null,
override val routerState: RouterState = RouterState()
) : HasRouterState
// Create your store with routing
val store = createStore<AppState>(AppState()) {
routing {
// Set initial route
initialRoute("/home")
// Define routes
content("/home") {
HomeScreen()
}
content("/profile", requiresAuth = true) {
ProfileScreen()
}
modal("/settings") {
SettingsModal()
}
}
}The library supports three distinct navigation layers:
Full screen replacements, typically for major navigation changes:
scene("/onboarding") {
OnboardingFlow()
}Standard navigation within the main content area:
content("/products") {
ProductListScreen()
}Overlay content that appears above the current screen:
modal("/filter") {
FilterModal()
}Protect routes with authentication requirements:
routing(
authConfig = AuthConfig(
authChecker = { state -> state.user != null },
unauthenticatedRoute = "/login"
)
) {
content("/profile", requiresAuth = true) {
ProfileScreen()
}
}Define different routes based on device characteristics:
content("/dashboard") {
whenCondition = RenderCondition.DeviceType(setOf(DeviceClass.Desktop, DeviceClass.Tablet))
DesktopDashboard()
}
content("/dashboard") {
whenCondition = RenderCondition.DeviceType(setOf(DeviceClass.Phone))
MobileDashboard()
}The routing library includes a powerful feature toggle system that enables:
class AppFeatureEvaluator : FeatureToggleEvaluator {
override fun <TState : StateModel> isFeatureEnabled(
state: TState,
featureName: String
): Boolean {
val appState = state as AppState
// Check remote config first
appState.remoteFeatures[featureName]?.let { return it }
// Local feature logic
return when (featureName) {
"premium_user" -> appState.user?.isPremium == true
"beta_features" -> appState.user?.isBetaTester == true
else -> false
}
}
}routing {
// Configure evaluator
featureToggles(AppFeatureEvaluator())
// Premium users see ad-free experience
scene("/movies", requiredFeature = "premium_user") {
PremiumMoviesScreen()
}
// Free users see ads
scene("/movies", requiredFeature = "free_tier") {
MoviesWithAdsScreen()
}
}// Direct state access
if (state.isFeatureEnabled("premium_features")) {
ShowPremiumContent()
}
// In composables with FeatureGate
@Composable
fun MovieScreen(store: KStore<AppState>) {
FeatureGate(store, "download_feature") {
DownloadButton()
}
// With fallback
FeatureGate(
store = store,
featureName = "hd_streaming",
fallback = { StandardPlayer() }
) {
HDPlayer()
}
}Configure how router state is restored:
routing {
restoration {
// Restore all routes (default)
restoreAll()
// Or restore only modals
restoreOnly(NavigationLayer.Modal)
// Or use conditional defaults
restoreWithDefaults {
when {
state.user == null -> "/login"
state.user.isOnboarded -> "/home"
else -> "/onboarding"
}
}
}
}// Navigate to a route
store.routeTo("/products")
// Navigate with parameters
store.routeTo("/product/details", param = Product(id = "123"))
// Go back
store.goBack()
// Show modal
store.showModal("/filter", param = FilterOptions())
// Dismiss modal
store.dismissModal()
// Pop to specific route
store.popToRoute("/home")A Kotlin Multiplatform routing library with advanced features for managing navigation in compose-based applications.
dependencies {
implementation("io.crowded-innovations:duks-routing:0.1.4")
}// Define your app state
@Serializable
data class AppState(
val user: User? = null,
override val routerState: RouterState = RouterState()
) : HasRouterState
// Create your store with routing
val store = createStore<AppState>(AppState()) {
routing {
// Set initial route
initialRoute("/home")
// Define routes
content("/home") {
HomeScreen()
}
content("/profile", requiresAuth = true) {
ProfileScreen()
}
modal("/settings") {
SettingsModal()
}
}
}The library supports three distinct navigation layers:
Full screen replacements, typically for major navigation changes:
scene("/onboarding") {
OnboardingFlow()
}Standard navigation within the main content area:
content("/products") {
ProductListScreen()
}Overlay content that appears above the current screen:
modal("/filter") {
FilterModal()
}Protect routes with authentication requirements:
routing(
authConfig = AuthConfig(
authChecker = { state -> state.user != null },
unauthenticatedRoute = "/login"
)
) {
content("/profile", requiresAuth = true) {
ProfileScreen()
}
}Define different routes based on device characteristics:
content("/dashboard") {
whenCondition = RenderCondition.DeviceType(setOf(DeviceClass.Desktop, DeviceClass.Tablet))
DesktopDashboard()
}
content("/dashboard") {
whenCondition = RenderCondition.DeviceType(setOf(DeviceClass.Phone))
MobileDashboard()
}The routing library includes a powerful feature toggle system that enables:
class AppFeatureEvaluator : FeatureToggleEvaluator {
override fun <TState : StateModel> isFeatureEnabled(
state: TState,
featureName: String
): Boolean {
val appState = state as AppState
// Check remote config first
appState.remoteFeatures[featureName]?.let { return it }
// Local feature logic
return when (featureName) {
"premium_user" -> appState.user?.isPremium == true
"beta_features" -> appState.user?.isBetaTester == true
else -> false
}
}
}routing {
// Configure evaluator
featureToggles(AppFeatureEvaluator())
// Premium users see ad-free experience
scene("/movies", requiredFeature = "premium_user") {
PremiumMoviesScreen()
}
// Free users see ads
scene("/movies", requiredFeature = "free_tier") {
MoviesWithAdsScreen()
}
}// Direct state access
if (state.isFeatureEnabled("premium_features")) {
ShowPremiumContent()
}
// In composables with FeatureGate
@Composable
fun MovieScreen(store: KStore<AppState>) {
FeatureGate(store, "download_feature") {
DownloadButton()
}
// With fallback
FeatureGate(
store = store,
featureName = "hd_streaming",
fallback = { StandardPlayer() }
) {
HDPlayer()
}
}Configure how router state is restored:
routing {
restoration {
// Restore all routes (default)
restoreAll()
// Or restore only modals
restoreOnly(NavigationLayer.Modal)
// Or use conditional defaults
restoreWithDefaults {
when {
state.user == null -> "/login"
state.user.isOnboarded -> "/home"
else -> "/onboarding"
}
}
}
}// Navigate to a route
store.routeTo("/products")
// Navigate with parameters
store.routeTo("/product/details", param = Product(id = "123"))
// Go back
store.goBack()
// Show modal
store.showModal("/filter", param = FilterOptions())
// Dismiss modal
store.dismissModal()
// Pop to specific route
store.popToRoute("/home")