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: A sealed interface that defines the possible platforms that the application can run on.System: A Debug build flag.
- security: Encryption, hashing, and UUID utilities.
Uuid: UUID generation via the best available platform algorithm.Cryptography: Encrypt/decrypt methods.
- telemetry: Logging and crash reporting.
Telemetry: Facade delegates to a pluggableTelemetryEngine.Loggeris the composite implementation: usesPlatformLoggerin dev mode andSentryLoggerin production.Consoleis an in-memory circular buffer for the in-app console feature.
Responsible for data persistence and retrieval.
- config: User preferences and configurations.
Config: Implements theConfigManagerinterface, responsible for fetching remote configs with a 1-hour cache TTL (zero in dev mode) and persisting, caching and exposingConfigsandPreferences. Uses a Mutex-protected file I/O to prevent race conditions.
- database: SQLDelight implementations and drivers.
DatabaseFactory: CreatesAppDatabase.Database: Database extension helpers.SqlIO: Sql extension helpers.SqlDriver: Creates the database driver.NoOpSqlDriver: A no-op implementation ofSqlDriver.
- http: Ktor client configuration and network logic.
HttpClientFactory: Configures Ktor with telemetry logging, timeouts, HTTP caching, encoding and JSON content negotiation.Network: Network status helpers.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.
- 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.FilePath: All local storage file paths.JsonFile: Handles JSON files persistence.
- 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 as a mutableStateFlowfor runtime toggling.
- usecase: Implementation of specific business workflows. Each feature is a sub-package containing the use case interface, its gateway implementation, additional models, and mappers, all co-located.
Gateways: Aggregates all gateways under a singleUseCasesinterface, injectingConfigManager,AppDatabase, andHttpClient.
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 (Serializable for nav arguments).Navigation: Composable that sets up theNavHostand defines all the possible navigation destinations within the app, linking eachScreento its corresponding composable content. Also provides theLocalNavController.Routing: Navigation extensions, a utility to safely open external URLs, and aChannelto decouple command sending defined inNavigatefrom theNavController, with backstack deduplication and a customNavTypefor passing complex objects.
- 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.StoreFactory: Factory for creatingStoreinstances.Screen: Wrapper composable handles the loading indicator and topbar with back button, help, music, and feedback callbacks.LoadingScreen: Default screen to show when the app is being setup and there are no dependencies available.
- 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