diff --git a/demos/stack-nav/build.gradle.kts b/demos/stack-nav/build.gradle.kts
new file mode 100644
index 000000000..d256a6854
--- /dev/null
+++ b/demos/stack-nav/build.gradle.kts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+plugins {
+ id("ribs.android.application")
+}
+
+android {
+ namespace = "com.uber.rib.stacknav"
+
+ defaultConfig {
+ applicationId = "com.uber.rib.stacknav"
+ targetSdk = 36
+ }
+}
+
+dependencies {
+ implementation(project(":libraries:rib-android"))
+ implementation(project(":libraries:rib-router-navigator"))
+ implementation(libs.androidx.appcompat)
+}
diff --git a/demos/stack-nav/src/main/AndroidManifest.xml b/demos/stack-nav/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..ecc1c4ada
--- /dev/null
+++ b/demos/stack-nav/src/main/AndroidManifest.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/RootActivity.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/RootActivity.kt
new file mode 100644
index 000000000..e13dce1ca
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/RootActivity.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav
+
+import android.view.ViewGroup
+import com.uber.rib.core.RibActivity
+import com.uber.rib.core.ViewRouter
+import com.uber.rib.stacknav.root.RootInteractor
+import com.uber.rib.stacknav.root.RootRouter
+import com.uber.rib.stacknav.root.RootView
+
+class RootActivity : RibActivity() {
+
+ override fun createRouter(parentViewGroup: ViewGroup): ViewRouter<*, *> {
+ val rootView = RootView(this)
+ val interactor = RootInteractor()
+ return RootRouter(rootView, interactor)
+ }
+}
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootInteractor.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootInteractor.kt
new file mode 100644
index 000000000..7c052e3ed
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootInteractor.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root
+
+import com.uber.rib.core.Bundle
+import com.uber.rib.core.EmptyPresenter
+import com.uber.rib.core.Interactor
+import com.uber.rib.stacknav.root.screen.ScreenInteractor
+
+/**
+ * Orchestrates the navigation stack. Pushes the first screen on start, and reacts to each screen's
+ * request to push the next one.
+ */
+class RootInteractor :
+ Interactor(EmptyPresenter()), ScreenInteractor.Listener {
+
+ override fun didBecomeActive(savedInstanceState: Bundle?) {
+ super.didBecomeActive(savedInstanceState)
+ router.pushScreen(1)
+ }
+
+ override fun onPushNextScreen(currentNumber: Int) {
+ if (currentNumber < MAX_SCREENS) {
+ router.pushScreen(currentNumber + 1)
+ }
+ }
+
+ override fun onBackRequested() {
+ router.popScreen()
+ }
+
+ companion object {
+ const val MAX_SCREENS = 5
+ }
+}
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootRouter.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootRouter.kt
new file mode 100644
index 000000000..b0f5cdace
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootRouter.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root
+
+import com.uber.rib.core.BasicViewRouter
+import com.uber.rib.core.RouterNavigator
+import com.uber.rib.core.StackRouterNavigator
+import com.uber.rib.stacknav.root.screen.ScreenInteractor
+import com.uber.rib.stacknav.root.screen.ScreenRouter
+import com.uber.rib.stacknav.root.screen.ScreenView
+
+/**
+ * Manages the screen stack using [StackRouterNavigator]. Each call to [pushScreen] pushes a new
+ * [ScreenRouter] on top; [handleBackPress] pops it.
+ */
+class RootRouter(
+ view: RootView,
+ interactor: RootInteractor,
+) : BasicViewRouter(view, interactor) {
+
+ private val navigator: RouterNavigator = StackRouterNavigator(this)
+
+ fun pushScreen(number: Int) {
+ val listener = interactor as ScreenInteractor.Listener
+ navigator.pushState(
+ ScreenState(number),
+ object : RouterNavigator.AttachTransition {
+ override fun buildRouter(): ScreenRouter {
+ val screenView = ScreenView(view.context, number, RootInteractor.MAX_SCREENS)
+ return ScreenRouter(screenView, ScreenInteractor(number, listener))
+ }
+
+ override fun willAttachToHost(
+ router: ScreenRouter,
+ previousState: ScreenState?,
+ newState: ScreenState,
+ isPush: Boolean,
+ ) {
+ view.addView(
+ router.view,
+ android.view.ViewGroup.LayoutParams(
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ android.view.ViewGroup.LayoutParams.MATCH_PARENT,
+ ),
+ )
+ }
+ },
+ object : RouterNavigator.DetachTransition {
+ override fun willDetachFromHost(
+ router: ScreenRouter,
+ previousState: ScreenState,
+ newState: ScreenState?,
+ isPush: Boolean,
+ ) {
+ view.removeView(router.view)
+ }
+ },
+ )
+ }
+
+ override fun handleBackPress(): Boolean {
+ if (navigator.size() > 1) {
+ navigator.popState()
+ return true
+ }
+ return false
+ }
+
+ fun popScreen() {
+ navigator.popState()
+ }
+
+ override fun willDetach() {
+ navigator.hostWillDetach()
+ super.willDetach()
+ }
+}
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootView.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootView.kt
new file mode 100644
index 000000000..a67d497c2
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/RootView.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root
+
+import android.content.Context
+import android.widget.FrameLayout
+
+/** Container that holds whichever screen is currently on top of the stack. */
+class RootView(context: Context) : FrameLayout(context)
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/ScreenState.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/ScreenState.kt
new file mode 100644
index 000000000..f33611e93
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/ScreenState.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root
+
+import com.uber.rib.core.RouterNavigatorState
+
+/** One entry in the navigation stack, identified by screen number. */
+data class ScreenState(val number: Int) : RouterNavigatorState {
+ override fun stateName() = "screen_$number"
+}
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenInteractor.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenInteractor.kt
new file mode 100644
index 000000000..df903d42b
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenInteractor.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root.screen
+
+import com.uber.rib.core.Bundle
+import com.uber.rib.core.EmptyPresenter
+import com.uber.rib.core.Interactor
+
+/**
+ * Interactor for a single screen. Wires the view's button to [Listener.onPushNextScreen] and cleans
+ * up on deactivation to avoid leaks.
+ */
+class ScreenInteractor(
+ private val screenNumber: Int,
+ private val listener: Listener,
+) : Interactor(EmptyPresenter()) {
+
+ interface Listener {
+ fun onPushNextScreen(currentNumber: Int)
+ fun onBackRequested()
+ }
+
+ override fun didBecomeActive(savedInstanceState: Bundle?) {
+ super.didBecomeActive(savedInstanceState)
+ router.view.onNextClicked = { listener.onPushNextScreen(screenNumber) }
+ router.view.onBackClicked = { listener.onBackRequested() }
+ }
+
+ override fun willResignActive() {
+ router.view.onNextClicked = null
+ router.view.onBackClicked = null
+ super.willResignActive()
+ }
+}
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenRouter.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenRouter.kt
new file mode 100644
index 000000000..3226e0298
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenRouter.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root.screen
+
+import com.uber.rib.core.BasicViewRouter
+
+/** Leaf router for a single numbered screen. No children. */
+class ScreenRouter(
+ view: ScreenView,
+ interactor: ScreenInteractor,
+) : BasicViewRouter(view, interactor)
diff --git a/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenView.kt b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenView.kt
new file mode 100644
index 000000000..7c236e923
--- /dev/null
+++ b/demos/stack-nav/src/main/kotlin/com/uber/rib/stacknav/root/screen/ScreenView.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2025. Uber Technologies
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.uber.rib.stacknav.root.screen
+
+import android.content.Context
+import android.graphics.Color
+import android.graphics.Typeface
+import android.util.TypedValue
+import android.view.Gravity
+import android.widget.Button
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+
+/**
+ * Full-screen view for a single stack entry. Includes a top navigation bar with an explicit back
+ * button (hidden on the root screen), the screen number in the centre, and a push button.
+ */
+class ScreenView(context: Context, screenNumber: Int, maxScreens: Int) : FrameLayout(context) {
+
+ var onNextClicked: (() -> Unit)? = null
+ var onBackClicked: (() -> Unit)? = null
+
+ private val screenColors =
+ listOf(
+ Color.parseColor("#1565C0"), // deep blue
+ Color.parseColor("#2E7D32"), // deep green
+ Color.parseColor("#E65100"), // deep orange
+ Color.parseColor("#6A1B9A"), // deep purple
+ Color.parseColor("#B71C1C"), // deep red
+ )
+
+ init {
+ val bg = screenColors[(screenNumber - 1) % screenColors.size]
+ setBackgroundColor(bg)
+
+ val dp = { n: Int ->
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n.toFloat(), resources.displayMetrics)
+ .toInt()
+ }
+
+ // ── Top navigation bar ──────────────────────────────────────────────────
+ val navBar =
+ LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.CENTER_VERTICAL
+ setBackgroundColor(Color.parseColor("#22000000"))
+ setPadding(dp(4), dp(4), dp(16), dp(4))
+ }
+
+ // Back button: a TextView styled as a tappable nav item
+ val backBtn =
+ TextView(context).apply {
+ text = "‹ Back"
+ setTextColor(Color.WHITE)
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
+ typeface = Typeface.DEFAULT_BOLD
+ setPadding(dp(12), dp(8), dp(16), dp(8))
+ visibility = if (screenNumber > 1) VISIBLE else INVISIBLE
+ isClickable = true
+ isFocusable = true
+ setOnClickListener { onBackClicked?.invoke() }
+ background = null
+ }
+
+ val navTitle =
+ TextView(context).apply {
+ text = "Screen $screenNumber"
+ setTextColor(Color.WHITE)
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
+ typeface = Typeface.DEFAULT_BOLD
+ gravity = Gravity.CENTER
+ layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
+ }
+
+ // Invisible placeholder mirrors the back button width so the title stays centred
+ val navEndSpacer =
+ TextView(context).apply {
+ text = "‹ Back"
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
+ setPadding(dp(12), dp(8), dp(16), dp(8))
+ visibility = INVISIBLE
+ }
+
+ navBar.addView(backBtn)
+ navBar.addView(navTitle)
+ navBar.addView(navEndSpacer)
+
+ // ── Body content ────────────────────────────────────────────────────────
+ val bigNumber =
+ TextView(context).apply {
+ text = "$screenNumber"
+ setTextColor(Color.WHITE)
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, 96f)
+ typeface = Typeface.DEFAULT_BOLD
+ gravity = Gravity.CENTER
+ }
+
+ val depth =
+ TextView(context).apply {
+ text = "Depth $screenNumber of $maxScreens"
+ setTextColor(Color.parseColor("#CCFFFFFF"))
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
+ gravity = Gravity.CENTER
+ setPadding(0, dp(4), 0, dp(40))
+ }
+
+ val nextButton =
+ Button(context).apply {
+ text =
+ if (screenNumber < maxScreens) "Push Screen ${screenNumber + 1} →" else "Stack is full"
+ isEnabled = screenNumber < maxScreens
+ setTextColor(Color.WHITE)
+ setBackgroundColor(Color.parseColor("#33FFFFFF"))
+ setPadding(dp(32), dp(12), dp(32), dp(12))
+ setOnClickListener { onNextClicked?.invoke() }
+ }
+
+ val body =
+ LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ gravity = Gravity.CENTER
+ addView(bigNumber)
+ addView(depth)
+ addView(nextButton)
+ }
+
+ // ── Root layout: nav bar pinned to top, body fills the rest ─────────────
+ val root =
+ LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ addView(
+ navBar,
+ LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ ),
+ )
+ addView(body, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f))
+ }
+
+ addView(root, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
+
+ // Push nav-bar content below the status bar on edge-to-edge displays (Android 15+).
+ // The background colour already extends behind the status bar, which looks intentional.
+ ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
+ val statusBarHeight = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top
+ navBar.setPadding(dp(4), statusBarHeight + dp(4), dp(16), dp(4))
+ insets
+ }
+ }
+
+ // Insets are dispatched once at window-attach time. Screens pushed later onto the stack
+ // are attached after that initial dispatch, so we re-request here to guarantee delivery.
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ ViewCompat.requestApplyInsets(this)
+ }
+}
diff --git a/demos/stack-nav/src/main/res/drawable-hdpi/ub__ic_launcher.png b/demos/stack-nav/src/main/res/drawable-hdpi/ub__ic_launcher.png
new file mode 100644
index 000000000..807d48f3c
Binary files /dev/null and b/demos/stack-nav/src/main/res/drawable-hdpi/ub__ic_launcher.png differ
diff --git a/demos/stack-nav/src/main/res/drawable-mdpi/ub__ic_launcher.png b/demos/stack-nav/src/main/res/drawable-mdpi/ub__ic_launcher.png
new file mode 100644
index 000000000..73900cc83
Binary files /dev/null and b/demos/stack-nav/src/main/res/drawable-mdpi/ub__ic_launcher.png differ
diff --git a/demos/stack-nav/src/main/res/drawable-xhdpi/ub__ic_launcher.png b/demos/stack-nav/src/main/res/drawable-xhdpi/ub__ic_launcher.png
new file mode 100644
index 000000000..4450b84e5
Binary files /dev/null and b/demos/stack-nav/src/main/res/drawable-xhdpi/ub__ic_launcher.png differ
diff --git a/demos/stack-nav/src/main/res/drawable-xxhdpi/ub__ic_launcher.png b/demos/stack-nav/src/main/res/drawable-xxhdpi/ub__ic_launcher.png
new file mode 100644
index 000000000..0039c30c2
Binary files /dev/null and b/demos/stack-nav/src/main/res/drawable-xxhdpi/ub__ic_launcher.png differ
diff --git a/demos/stack-nav/src/main/res/drawable-xxxhdpi/ub__ic_launcher.png b/demos/stack-nav/src/main/res/drawable-xxxhdpi/ub__ic_launcher.png
new file mode 100644
index 000000000..e35a057e7
Binary files /dev/null and b/demos/stack-nav/src/main/res/drawable-xxxhdpi/ub__ic_launcher.png differ
diff --git a/demos/stack-nav/src/main/res/values/strings.xml b/demos/stack-nav/src/main/res/values/strings.xml
new file mode 100644
index 000000000..fa946e9a7
--- /dev/null
+++ b/demos/stack-nav/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Stack Nav Demo
+
diff --git a/demos/stack-nav/src/main/res/values/styles.xml b/demos/stack-nav/src/main/res/values/styles.xml
new file mode 100644
index 000000000..74c694c31
--- /dev/null
+++ b/demos/stack-nav/src/main/res/values/styles.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/settings.gradle b/settings.gradle
index 6e224e2ce..a3c886313 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -56,3 +56,4 @@ include ':demos:intellij'
include ':demos:memory-leaks'
include ':demos:compose'
include ':demos:rib-workers'
+include ':demos:stack-nav'