Skip to content

Welcome to ⚓️ anchor

GitHub Follow @k10b4

Anchor is a simple, lightweight, and extensible state management architecture built on Kotlin's Context receivers with Jetpack Compose integration for Kotlin Multiplatform projects.

Goal

Focus on writing an amazing app and let Anchor handle the state and side effects!

Key Features

  • Built for Compose: Native integration with Jetpack Compose.
  • Kotlin Multiplatform: Supports Android and iOS.
  • Type-Safe: Leverages Kotlin's type system for state, effects, signals, and events.
  • Lifecycle-Aware: Automatically manages Anchor instances within ViewModels, retaining state across configuration changes.
  • Context Receivers: Uses modern Kotlin features for a clean and expressive DSL.
  • Granular Recomposition: Provides utilities to observe only the necessary parts of the state.

Installation

Anchor is available on Maven Central. Add the dependencies to your build.gradle.kts:

dependencies {
    implementation("dev.kioba.anchor:anchor:0.1.1")
    implementation("dev.kioba.anchor:anchor-compose:0.1.1")
    testImplementation("dev.kioba.anchor:anchor-test:0.1.1")
}
Module Purpose
anchor Core state management (ViewState, Effect, Anchor, Signals, Events)
anchor-compose Jetpack Compose bindings (RememberAnchor, collectState, anchor(), HandleSignal)
anchor-test BDD-style testing DSL (runAnchorTest, given/on/verify)

Quick Start (Counter Example)

Here's a simple counter example to get you started:

// 1. Define your State
data class CounterState(val count: Int = 0) : ViewState

// 2. Define your Anchor
typealias CounterAnchor = Anchor<EmptyEffect, CounterState, Nothing>

fun RememberAnchorScope.counterAnchor(): CounterAnchor =
    create(initialState = ::CounterState, effectScope = { EmptyEffect })

// 3. Define Actions
fun CounterAnchor.increment() {
    reduce { copy(count = count + 1) }
}

// 4. Use in UI
@Composable
fun CounterScreen() {
    RememberAnchor(scope = { counterAnchor() }) {
        val count = collectState { it.count }
        Button(onClick = anchor(CounterAnchor::increment)) {
            Text("Count: $count")
        }
    }
}

Next Steps


License

Copyright 2026 Karoly Somodi

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.