An App Bundle can hold more than the base app. A dynamic feature module is a Gradle 19,597 module that Play delivers separately, in one of three ways: at install time (the default), on demand when the app asks for it, or conditionally by device features, country or API level. A JavaScript bundle can't be split this way; a native app can keep rarely used screens off every phone that never opens them (Google warns that 50 or more such modules on one device may hurt performance).
BookNest moves a monthly Book Club page into an on-demand module, :bookclub. Its build.gradle.kts applies com.android.dynamic-feature and depends on project(":app") (a feature depends on the base, not the reverse); :app adds dynamicFeatures += setOf(":bookclub") and feature-delivery-ktx 2.1.0, and the feature's manifest declares the delivery:
<dist:module dist:title="@string/title_bookclub">
<dist:delivery>
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="true" />
</dist:module>The title, which Play may show when it asks the user to confirm a download, must live in the base module (title_bookclub in :app's strings.xml); fusing matters only for the single APK built for devices older than Android 5.0, far below BookNest's minSdk. The base cannot reference the feature's classes at compile time, so play/BookClubLauncher.kt checks splitInstallManager.installedModules, and if "bookclub" is missing calls startInstall() with a SplitInstallRequest for it; a listener logs each SplitInstallSessionStatus and, at INSTALLED, starts com.example.booknest.bookclub.BookClubActivity by name. SplitCompat.install() in BookNestApp and SplitCompat.installActivity() in that activity load the new code without a restart (Publishing the Native BookNest runs it).
Two checks on the bundle are worth repeating. Google warns that resource shrinking can delete the module title if base code never references it; bundletool 4,040 dump resources --resource=string/title_bookclub showed "Book Club" still in BookNest's release, but a tools:keep resource file is the fix if it disappears. And bundletool dump manifest --module=bookclub showed targetSdkVersion="37" in the split, copied from its compileSdk: AGP 9 has no targetSdk for feature modules (adding one failed with Unresolved reference 'targetSdk'), and the app's target still comes from the base, which the device reported as targetSdk=36.