Frontend
This document covers the frontend web distribution model, Compose dependency versioning rules, and frontend-app repository and ViewModel conventions.
For the broader system map, see architecture-overview.md.
frontend-app Web Distribution
frontend-app no longer builds or deploys its own container image. Its JS browser distribution is published as the consumable webDistElements directory artifact backed by jsBrowserDevelopmentExecutableDistribution.
backend-web-app resolves that artifact, stages it into build/caddy/dist, and packages it into the production Caddy image. backend-web-app:assemble pulls the frontend distribution transitively.
Frontend Compose Dependency Versioning
Frontend Compose modules currently include frontend-app and frontend-charts.
- Prefer version-catalog aliases such as
libs.compose.runtime,libs.compose.foundation,libs.compose.ui, andlibs.compose.html.corein dependency blocks. Do not use the deprecatedcompose.*dependency accessors there; keepcompose.desktop.currentOsonly for the desktop target artifact. - Keep
org.jetbrains.compose.*modules on the sharedcomposeversion ingradle/libs.versions.toml. - Keep
org.jetbrains.compose.material3:material3on the separatecompose-material3version because it does not track the rest of the JetBrains Compose modules. - Keep AndroidX Compose-adjacent families on their own version refs:
org.jetbrains.androidx.lifecycle,org.jetbrains.androidx.navigation,androidx.savedstate, andandroidx.activity:activity-compose. - Add
compose.foundationexplicitly when frontend code uses layout, focus, scrolling, pointer-input, or other foundation APIs; do not rely on those APIs arriving transitively. - Any module that uses Kotest artifacts should import
platform(libs.kotest.bom)in the relevant configuration/source set instead of versioning individual Kotest modules directly.
frontend-app Repository And ViewModel Conventions
FeedsRepositoryandStrategiesRepositoryare internal interfaces with private in-file implementations. Construct them viacompanion object { operator fun invoke(...) }and keep DI wiring inAppComponentpointing at those factories.- Prefer mocking those repository interfaces directly in
commonTestrather than introducing extra port types just forViewModeltests. - Shared instrument-search UI state should stay generic over a feature-owned mode type. Keep
instrumentsearch.ViewModeas the shared interface withdisplayValue, define per-screen enums such asFeedsViewModeandStrategiesViewModein the owning feature package, and thread them throughInstrumentSearchViewState<TViewMode>/SearchView<TViewMode>so eachViewModelkeeps exhaustive mode handling without meaningless cross-screen values. - For
ViewModelsearch/filter logic, keep helper functions private and verify behavior through exposed flows such assearchViewStateinstead of widening visibility for tests. - Prefer private top-level helpers over nested local functions when extracting non-trivial
ViewModellogic.
frontend-app Test Conventions
frontend-app is a Kotlin Multiplatform UI module, so its verification is target-specific rather than a single JVM test task:
- Shared
ViewModeltests live insrc/commonTestand use KotestFunSpec, Mokkery mocks, Turbine flow assertions, andandroidx.lifecycle.viewmodel.testing.viewModelScenario. CoroutineTestExtensioninsrc/commonTestsetsDispatchers.Mainbefore each test and resets it afterward. Specs that use it should enable Kotest's coroutine test scope (coroutineTestScope = true) so the test body runs under virtual time.viewModelScenario { ... }.use { ... }is the preferred harness forViewModellifecycle tests in common code.- Android host unit tests for
frontend-apprun throughtestDebugUnitTest; keepandroid.testOptions.unitTests.isReturnDefaultValues = truebecauseviewModelScenarioreaches AndroidBundleAPIs that otherwise throw "not mocked" errors under local unit tests. - Verify frontend-app changes with
./gradlew :frontend-app:testDebugUnitTest :frontend-app:desktopTest :frontend-app:jsTestwhen the change touches sharedViewModeltests or other code exercised by Android host tests. In CI, the root unit-test step runs./gradlew test allTests, which covers backend JVM tests plus KMPallTeststasks such as:frontend-app:allTests.
Related Documents
- architecture-overview.md — frontend delivery model in context
- testing.md — full test suite layout including frontend-app test suites
- build-system.md — Compose versioning catalog and Gradle dependency rules