Skip to content

Instantly share code, notes, and snippets.

View AndroidPoet's full-sized avatar
God Mode

Ranbir Singh AndroidPoet

God Mode
View GitHub Profile

I Built a Leaner Supabase SDK for Kotlin Multiplatform. Here’s Why It’s Architecturally Better

Android Poet

5 min read

How trading framework-heavy SDK design for explicit results, typed IDs, direct composition, and Kotlin-first APIs made Supabase feel cleaner in Kotlin Multiplatform.

When I first started building Kotlin Multiplatform apps with Supabase, I reached for the official Kotlin SDK.

result
.onSuccess { cities -> println(cities) }
.onFailure { error -> println(error.message) }
val result = database.selectTyped<City>(
table = "cities",
) {
eq("name", "Paris")
}
val data = supabase.postgrest["cities"]
.select {
City::name eq "Paris"
}
.decodeList<City>()
@Serializable
data class Todo(
val id: String,
val title: String,
val done: Boolean,
)
val todos = database.selectTyped<Todo>(
table = "todos",
) {
val auth = createAuthClient(client)
val database = createDatabaseClient(client)
val storage = createStorageClient(client)
val realtime = createRealtimeClient(client)
val functions = createFunctionsClient(client)
val client = Supabase.create(
projectUrl = "https://your-project.supabase.co",
apiKey = "your-anon-key",
) {
logging = true
}
[versions]
supabase-kmp = "0.3.2"
[libraries]
supabase-core = { module = "io.github.androidpoet:supabase-core", version.ref = "supabase-kmp" }
supabase-client = { module = "io.github.androidpoet:supabase-client", version.ref = "supabase-kmp" }
supabase-auth = { module = "io.github.androidpoet:supabase-auth", version.ref = "supabase-kmp" }
supabase-auth-admin = { module = "io.github.androidpoet:supabase-auth-admin", version.ref = "supabase-kmp" }
supabase-database = { module = "io.github.androidpoet:supabase-database", version.ref = "supabase-kmp" }
supabase-storage = { module = "io.github.androidpoet:supabase-storage", version.ref = "supabase-kmp" }
val bucketId = BucketId("avatars")
getUser(bucketId) // Compile error if getUser expects UserId
@JvmInline
value class UserId(val value: String)
@JvmInline
value class BucketId(val value: String)
@JvmInline
value class ChannelId(val value: String)