Small Kotlin Multiplatform app built to learn KMP, with shared UI and logic across Android, Web, and the server. (done with the Claude help)
A receipt archiver for Slovak eKasa fiscal receipts. Scan the QR code printed on a shop receipt, and the app looks it up via the eKasa API, saves it, and shows it in a searchable list with itemized detail — from Android or a browser.
core— shared API DTOs and the Ktor HTTP client used by both frontends.app/shared— the Compose Multiplatform UI (list, detail, scanner screens) shared between Android and Web.app/androidApp— Android entry point; the only target with the QR scanner.app/webApp— Kotlin/Wasm entry point, compiled to a static web bundle.server— Ktor backend: REST API, eKasa client, SQLite persistence via Exposed, and static hosting of the web bundle.
- Server:
./gradlew :server:run(port 8081) - Web app:
./gradlew :app:webApp:wasmJsBrowserDevelopmentRun(port 8080) - Android app:
./gradlew :app:androidApp:assembleDebug(or run from Android Studio; pointAPI_BASE_URLinMainActivity.ktat your server's address,
The server reads its configuration from environment variables:
| Variable | Default | Description |
|---|---|---|
PORT |
8081 |
HTTP port |
HOST |
0.0.0.0 |
Bind address |
DB_PATH |
/data/receipts.db |
SQLite database file |
EKASA_BASE_URL |
https://ekasa.financnasprava.sk |
eKasa API base URL |
WEB_DIR |
/app/web |
Static web bundle directory served at / |
The API and the web UI are served on the same port — /api/* routes handle the REST API, and
everything else falls back to the static web bundle (with SPA-style fallback to index.html).
Build and run as a single container:
docker build -t receipts .
docker run -p 8080:8080 -v receipts-data:/data receiptsThe image bundles both the server and the pre-built web app; receipts persist in the /data
volume.