The code for this example is available in the
Trails repository.
Prerequisites
Quick Links to Prerequisites:
- Kotlin Multiplatform Project Setup: Basic understanding of KMP and a project set up with shared 
commonMaincode. - Coroutines and Flow: Basic understanding of Kotlin Coroutines and Flow for asynchronous programming.
 - Gradle: Familiarity with Gradle for dependency management.
 
Installation
1
Add the Dependency
Add the Store library to your project’s dependencies. Since we’re working with a KMP project, we’ll add the dependency to the 
commonMain source set.libs.versions.toml
build.gradle.kts
Understanding Version Catalogs:The For more information on Version Catalogs, visit the Gradle Documentation.
libs.versions.toml file is part of Gradle’s Version Catalogs feature, which simplifies dependency management.If you’re not using Version Catalogs, you can add the dependency directly to your build.gradle.kts:2
Sync the Project
After adding the dependency, sync your project with Gradle to download the Store library.
Building a Store
Now, let’s build a simple Store to fetch and cache posts from our API and cache it for offline access.1
Define the Data Models
Define the models for a post.
Using SqlDelight for Local Database Models:The SQL schema defined using SqlDelight will generate Kotlin models for you. Here’s how the For more details on how SqlDelight generates Kotlin classes from SQL schemas, check out the SqlDelight Docs.
PostEntity class might look after generation:2
Create the API Interface
Define and implement an interface for your network calls. In this example, we’ll use Ktor for HTTP requests.
Dependency Injection Context:Trails uses kotlin-inject, a compile-time dependency injection library for Kotlin. The 
@Inject annotation indicates a class can be injected.3
Implement Converters
We need to convert between our network model, domain model, and local database model.
4
Set Up the Store Factory
We’ll use a factory for creating a 
PostStore instance.About the 
TODO() Placeholders:The TODO() placeholders indicate where implementations will be provided in the subsequent steps.5
Implement the Fetcher
Our Fetcher will interact with the network data source using the 
PostOperations interface.6
Implement the Source of Truth
Our Source of Truth will delegate to a local SqlDelight database.
Observing Database Changes Over Time:To ensure your 
SourceOfTruth observes changes in the database, use asFlow() and appropriate mapping functions.7
Implement the Converter
Our Converter will convert between our network model, local database model, and domain model using the 
PostExtensions object.Understanding the Converter’s Role:The Converter bridges the gap between the network model, local database model, and domain model within the Store.While you have extension functions for conversions, the Converter integrates these into the Store’s pipeline, ensuring data flows correctly through each layer.
8
Implement the Updater
Our Updater will make a network call to update the post.
9
Implement the Bookkeeper
Our Bookkeeper keeps track of failed syncs to enable eagerly resolving conflicts after local mutations.
10
Build the Store
Provide the implementations to the Store Builder.
How Components Work Together:Each component of the Store has a specific role:
Fetcher: Retrieves data from the network.Source of Truth: Manages local data storage.Converter: Handles data transformations between models.Updater: Syncs local changes back to the network.Bookkeeper: Keeps track of failed updates for retry mechanisms.
Using the Store
Now, let’s use the Store to fetch and cache post data for the Trails post detail screen.1
Create a Post Repository
We’ll create a 
PostRepository that uses the PostStore to fetch and cache post data. The primary reason for this extra layer is it enables us to extract Store from the domain layer as an implementation detail of the PostRepository. It also enables us to add additional methods and strategies to the PostRepository in the future.PostRepository is feature agnostic. We define the PostRepository under the
common lib/market/post/api namespace and implement it in the
lib/market/post/impl module to facilitate its reuse across features.
Consumers can depend on the lib/market/post/api module without being exposed
to the implementation details, such as the PostStore.A market is a composition of stores and systems enabling exchange between
consumers and providers.
2
3
Implement the Post Detail Presenter
A Circuit Presenter is intended to be the business logic for a screen’s UI and a translation layer in front of the data layer. Our 
PostDetailScreenPresenter will use the PostRepository to load the post data and update the UI in response to user actions.4
Display the Post Detail Screen