There is no special support needed to use Ballast in Compose applications, and it works on Android, Desktop, iOS, and JS targets (WASM support coming soon). For JS, it can also be used with both Canvas and Compose HTML applications. The integration process for all of these use-cases is the same.


A good pattern for defining the Compose UI with Ballast State Management is to create a single object with two main functions for the UI. One which is fully stateless, taking parameters of only the VM state and a postInput callback, and another which creates and manages the Ballast ViewModel that internally calls the stateless version.

public object ExampleUi {

    public fun Content() {
        // this can 
        val viewModelCoroutineScope = rememberCoroutineScope()
        val vm: ExampleViewModel = remember(viewModelCoroutineScope) {
                coroutineScope = viewModelCoroutineScope,
                config = BallastViewModelConfiguration.Builder()
                        initialState = ExampleContract.State(),
                        inputHandler = ExampleInputHandler(),
                eventHandler = ExampleEventHandler(),
        // collect the VM state and call the stateless Content() function
        val uiState by vm.observeStates().collectAsState()

        Content(uiState) { vm.trySend(it) }

    public fun Content(
        uiState: ExampleContract.State,
        postInput: (ExampleContract.Inputs) -> Unit,
    ) {
        // ...