App Bootstrap.
- Android
- iOS
- Windows
- macOS
- Linux
- Web
This is a Kotlin Multiplatform project following Clean Architecture. Its design ensures that the business logic remains platform-agnostic with a strict Unidirectional Dependency Flow. It targets Android, iOS, Desktop (JVM), and Web (WASM-JS) and is composed of 3 main modules:
shared: contains code that is reused across all target platforms (Client and Server).server: acts as the backend for the application.composeApp: client side. All shared code lives undercomposeApp/src/commonMain/.
- UI: Compose Multiplatform
- Client Database: SQLDelight
- Server Database Exposed
- Networking: Ktor
- Monitoring: Sentry
- Code Coverage: Kover
| Source Set | Platform |
|---|---|
androidMain |
Android API 26+ |
appleMain |
iOS 16+ / macOS |
desktopMain |
JVM 21 |
webMain |
WASM-JS |
server |
JVM 21 |
Business logic agnostic implementations.
- audio: Audio Player implementation.
AudioPlayer: Abstraction with a sealedActioninterface (Play, Pause, Resume, Toggle). Manages playlist deduplication and shuffling and delegates platform-specific playback to subclasses.
- flow: Coroutine dispatchers.
Dispatcher: ProvidesMain,DefaultandIOcoroutine dispatchers as mutable properties so tests can substitute their own implementations.
- locale: Localization and date/time formatting.
Locale: Methods to get the current system language (Language), locale-aware datetime formatting, and aFlowthat emits on locale changes.DateTime: Utilities for getting the current time in UTC/ISO8601, epoch and duration calculation.Language: App default language and other language listings.
- platform: OS-specific APIs.
Platform: Provides a snapshot of the current execution environment with a sealed interface that defines the possible platforms that the application can run on.System: Debug build flag, Properties and Env definitions.
- security: Cryptography and UUID utilities.
Uuid: UUID generation via the best available platform algorithm.Cryptography: Cryptography methods like encrypt/decrypt and hashing.
- telemetry: Logging and crash reporting.
Telemetry: Facade delegates to a pluggableTelemetryEngine.Logger: Composite implementation: usesPlatformLoggerorServerLoggerfor Client and Server respectively in dev mode andSentryLoggerin production.Console: An in-memory circular buffer for the in-app console feature.
Responsible for data persistence and retrieval.
- database: SQLDelight and Exposed implementations, tables and drivers.
DatabaseFactory: CreatesAppDatabaseorR2dbcDatabasefor Client and Server respectively.Database: Database extension helpers.SqlIO: Sql extension helpers.SqlDriver: Creates the database driver.NoOpSqlDriver: A no-op implementation ofSqlDriver.
- http: Ktor configuration and network logic.
HttpClientFactory: Configures Ktor with telemetry logging, timeouts, HTTP caching, encoding and JSON content negotiation.Network: Network status helpers.Header: Header constants used for communication and telemetry.Http: Extensions to execute type-safe requests and decode the response into aResult<Success|Error>.URL: Sealed class of all remote endpoints.HttpEngine: Creates the http engine.NoOpHttpEngine: A no-op implementation ofHttpClientEngine. Returns 204 for every request.
- resource: Resource index.
AudioResource: Resource index for audio incommonMain/resources/tracks.ImageResource: Resource index for images incommonMain/composeResources/drawable.JsonResource: Resource index for JSONs incommonMain/composeResources/files.ResourceLoader: Loads resources via the Compose Resources API.
- scheduler: Scheduler implementation.
Job: A persistent background execution unit handled by the scheduling subsystem.Scheduler: Orchestrates dispatch logic by managing job queues destined for persistent execution.
- serializer: JSON parsing and serialization.
Json: Helpers for encoding/decoding and URL-safe serialization.
- storage: File system access.
File: Declarations for getting the app data directory and suspending save/load/delete file operations.Storage: Implements byStorageFileinterface to manage the state and persistence of key-value files. Uses a Mutex-protected I/O to prevent race conditions.
- translation: Translation related tools.
TranslationCache: A cache dedicated to translations since most of the fetching is done onMain, thus eliminating the performance bottleneck of I/O.
Business rules and entities. Models are defined at root level in their respective package.
- flag: Feature flags.
Flags: Data class with boolean controls for feature flags.FeatureFlags: Exposes flags for runtime toggling.
- usecase: Implementation of specific business workflows. Each use case is a sub-package containing the interface and its gateway implementation.
Gateways: Aggregates all gateways under theUseCasesfile.
What the user interacts with.
At root level we find the main composable function App that assembles the application UI and acts as the top-level container for the user-facing elements, and Preview which is a wrapper composable for Previews.
- lifecycle: Platform-aware lifecycle observers.
Lifecycle: Composable that registers foreground/background callbacks, with an optional recomposition key.
- navigation: Routing logic and navigation graph definitions.
Screen: Sealed interface that enumerates all destinations.Navigation: Composable that sets up the navigation and defines all the possible navigation destinations within the app, linking eachScreento its corresponding composable content.Routing: Navigation extension functions.
- screen: UI screens implementations. Each screen is a sub-package containing the screen composable and respective store for state management, all co-located.
Store:ViewModelwith aStateFlow<State>as the single source of truth for the UI and reducer override to process actions from the UI.Screen: Wrapper composable that provides the foundational UI.
- theme: Design system and component definition.
Theme: Main app theme definition that usesLocalColorSchemeprovided byColor,LocalShapesprovided byShapesandLocalTypographyprovided byTypography.Translations: Composable helpers to read fromTranslationCache. ProvidesLocalTranslationState.
Test utilities like annotations and fake data shared across test source sets.
The testing structure mirrors the source code to ensure 1:1 coverage.
Manual, no framework. At root level, we find the Dependency class that wires everything together.
Application is the singleton entry point that initializes Dependency and telemetry, and holds feature flags and global listeners.
At the ui package root, we find App: the main composable that assembles the application UI and acts as the top-level container for the user-facing elements. Uses the composition locals: LocalTranslationState, LocalNavController.
Compose screens use a custom MVI Store pattern. Each screen has a Store ({Screen}Store) and a Screen composable ({Screen}Screen). Jobs inside a Store can be launched with an ID to cancel/replace prior work.
The UI state uses kotlinx.collections.immutable (ImmutableList, ImmutableSet) to prevent accidental mutations.
Create a local.properties file in the root directory. This is used for Sentry, Android signing, and Apple notarization.
- sentryDsn=YOUR_SENTRY_DSN
- android.storeFile=path/to/keystore.jks
- android.keyAlias=alias
- android.keyPassword=password
- android.storePassword=password
- mac.sign.identity=AppleID
- mac.notarization.appleId=email@example.com
- mac.notarization.teamId=TEAMID
- mac.notarization.password=password