Skip to content

SeijinD/KMPWebRoom

Repository files navigation

KMP Web Room

A minimal Kotlin Multiplatform project demonstrating Room 3 database running in the browser via Kotlin/Wasm and SQLite OPFS.

Data is stored persistently in the browser using the Origin Private File System (OPFS) — a real SQLite database that survives page refreshes.

Architecture

┌─────────────────────────────────────────────────────┐
│                    commonMain                       │
│  ┌──────────┐  ┌──────────┐  ┌───────────────────┐  │
│  │NoteEntity│  │ NoteDao  │  │   AppDatabase     │  │
│  │ @Entity  │  │  @Dao    │  │ @ConstructedBy    │  │
│  └──────────┘  └──────────┘  └───────────────────┘  │
│                                    │                │
│                       expect getDatabaseBuilder()   │
└────────────────────────────────────┬────────────────┘
                                     │
┌────────────────────────────────────▼────────────────┐
│                   wasmJsMain                        │
│                                                     │
│  actual fun getDatabaseBuilder()                    │
│    Room.databaseBuilder(name = "notes.db")          │
│      .setDriver(WebWorkerSQLiteDriver(...))         │
│                         │                           │
│            @JsFun → new Worker('worker.js')         │
│                    Web Worker thread                │
│                  ┌──────────────────┐               │
│                  │ SQLite WASM      │               │
│                  │ OPFS storage     │               │
│                  └──────────────────┘               │
└─────────────────────────────────────────────────────┘

Tech Stack

Library Version
Kotlin 2.3.20
Compose Multiplatform 1.10.3
Room 3.0.0-alpha03
AndroidX SQLite Web 2.7.0-alpha03
KSP 2.3.6
Koin 4.2.0

Run

./gradlew composeApp:wasmJsBrowserDevelopmentRun

Opens at http://localhost:8080.

Note: The dev server is configured with Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers, required for SharedArrayBuffer / OPFS.

Project Structure

composeApp/
├── sqlite-wasm-worker/              # Local npm package — SQLite Web Worker
│   ├── package.json
│   └── worker.js
├── webpack.config.d/
│   └── cors-headers.js              # COOP/COEP headers for OPFS
├── src/
│   ├── commonMain/kotlin/.../
│   │   ├── data/
│   │   │   ├── NoteEntity.kt       # @Entity
│   │   │   ├── NoteDao.kt          # @Dao with Flow
│   │   │   ├── AppDatabase.kt      # @Database + @ConstructedBy
│   │   │   └── DatabaseBuilder.kt   # expect fun
│   │   ├── di/
│   │   │   └── AppModule.kt        # Koin module
│   │   └── ui/
│   │       ├── App.kt              # Compose UI
│   │       └── NotesViewModel.kt   # ViewModel with StateFlow
│   └── wasmJsMain/kotlin/.../
│       ├── data/
│       │   └── DatabaseBuilder.wasmJs.kt  # actual — WebWorkerSQLiteDriver
│       └── main.kt                        # Entry point + Koin init
└── build.gradle.kts

How It Works

The Room database layer (Entity, DAO, Database) lives in commonMain — identical to Android. The only web-specific part is the actual fun getDatabaseBuilder() which uses WebWorkerSQLiteDriver to bridge Room with a SQLite instance running inside a Web Worker via OPFS.

The worker.js is the official AndroidX reference implementation and handles four commands over postMessage: open, prepare, step, close.

References

License

Copyright 2026 Georgios Karanikolas

Licensed under the Apache License, Version 2.0

See LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors