sqlite-web-viewer
0.5.1indexedEmbed a tiny HTTP server in an app to browse SQLite databases via a web UI: inspect tables/views, run raw SQL, view schema, decode JSON, auto-reload, multi-database support.
Embed a tiny HTTP server in an app to browse SQLite databases via a web UI: inspect tables/views, run raw SQL, view schema, decode JSON, auto-reload, multi-database support.
Browse the SQLite databases inside your running app from a web browser. SQLite Web Viewer embeds a tiny HTTP server in your application that serves a web UI (built with SolidJS) for inspecting tables, running queries, and viewing schema — no need to pull the database file off the device.
It is published as a Kotlin Multiplatform library, so the same viewer runs on Android, JVM, and iOS.
┌─────────────┐ HTTP ┌──────────────────────────┐
│ Browser │◄──────────► │ Embedded server (Ktor) │
│ (web UI) │ /query │ in your app process │
└─────────────┘ └────────────┬─────────────┘
│ Queryable
▼
Your SQLite db(s)
Your app supplies one or more Queryables (an abstraction over "run these SQL
statements in a transaction"). The library serves the bundled web UI and proxies
its queries to your databases.
The library is published to Maven Central (see PUBLISHING.md):
dependencies {
implementation("io.github.simophin:sqlite-web-viewer:<version>")
}
val queryable = SupportQueryable(myOpenHelper.writableDatabase)
val instance = startDatabaseViewerServer(
context = this, // an Activity
port = 3000,
queryable = queryable,
)
// Later, to shut it down:
instance.stop()
Then open http://<device-ip>:3000/ in a browser (e.g. via adb forward tcp:3000 tcp:3000 and visit http://localhost:3000/).
Instead of a fixed set, provide a QueryableFactory. It is consulted afresh on
every request, so the available databases can change at runtime, and each
Queryable is only resolved when a request actually targets it (handy for
opening connections on demand):
val factory = : QueryableFactory {
= listOf(, , )
: Queryable? = (id) {
-> SupportQueryable(usersDb)
-> SupportQueryable(productsDb)
-> SupportQueryable(logsDb)
->
}
}
instance = startDatabaseViewerServer(
context = ,
port = ,
factory = factory,
)
This serves an index at / linking to /users/, /products/, and /logs/,
each with its own viewer. If you already hold every database up front, the map
form is equivalent:
startDatabaseViewerServer(
context = this,
port = 3000,
factory = QueryableFactory(mapOf("users" to usersQueryable, /* ... */)),
)
See demoapp for a runnable example serving several
in-memory databases.
val driver = BundledSQLiteDriver()
val queryable = SqliteQueryable { driver.open(":memory:") }
val instance = startDatabaseViewerServerShared(
port = 3000,
queryable = queryable, // or: databases = mapOf(...)
assetProvider = ClasspathStaticAssetProvider(),
)
The JVM module also has a runnable main (./gradlew :sqlite-web-viewer:jvmRun),
configurable via the DB_PATH environment variable.
startDatabaseViewerServer(port = 3000, queryable = queryable)
The web UI is served from the app bundle via NSBundleAssetProvider.
The web UI must be built before the library, since its bundle is packaged into the artifact:
cd webapp
npm ci
npm run build
cd ../android_lib
./gradlew :sqlite-web-viewer:publishToMavenLocal # or build the demo app
webapp/ — the SolidJS web UI (README)android_lib/library/ — the Kotlin Multiplatform embedded-server libraryandroid_lib/demoapp/ — an Android sample appSurfaced from shared tags and platforms — no rankings paid for.