Android (Kotlin)
Build and query a ZXCV database from an Android app, then ship it to the edge. You’ll end with a screen that reads live data.
Create a project
In the dashboard click Start building, or run zxcv
from your terminal. Open Settings → API and copy your project ref and
anon key — the anon key is public and safe to ship, because access is enforced
server-side by your authorization rules.
Create a table
In the SQL editor, create a todos table with a couple of rows:
create table todos (
id bigint generated always as identity primary key,
title text not null,
is_complete boolean not null default false
);
insert into todos (title) values ('Read the docs'), ('Ship an app');Install the SDK
Add the io.zxcv:zxcv-kotlin dependency to your app-module build.gradle.kts:
dependencies {
implementation("io.zxcv:zxcv-kotlin:1.0.0")
}Then sync Gradle:
./gradlew buildInitialize the client
Create the client once in your Application subclass so it lives for the whole
process, and register it in your AndroidManifest.xml. The anon key is safe to
ship in client code:
import android.app.Application
import io.zxcv.ZXCVClient
class App : Application() {
override fun onCreate() {
super.onCreate()
zxcv = ZXCVClient(project = "acme-store", anonKey = "your-anon-key")
}
companion object {
lateinit var zxcv: ZXCVClient
private set
}
}Register the class in AndroidManifest.xml with
<application android:name=".App" ... >. For real projects, keep your keys out
of source with a BuildConfig field fed from local.properties rather than
hard-coding them.
Fetch and render
Fetch the rows in a coroutine off viewModelScope, expose them as state, and
render them with a Jetpack Compose LazyColumn:
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
data class Todo(val id: Long, val title: String, val isComplete: Boolean)
class TodosViewModel : ViewModel() {
private val _todos = MutableStateFlow<List<Todo>>(emptyList())
val todos = _todos.asStateFlow()
init {
viewModelScope.launch {
_todos.value = App.zxcv
.from("todos")
.select("id, title, is_complete")
.order("id")
}
}
}
@Composable
fun TodosScreen(viewModel: TodosViewModel) {
val todos by viewModel.todos.collectAsStateWithLifecycle()
LazyColumn {
items(todos) { todo ->
Text(text = todo.title)
}
}
}Deploy
Ship your project to the global edge from your terminal:
npm i -g zxcv
zxcv link acme-store
zxcv deploy --prodEvery push gets a preview URL; --prod promotes to your domain. See
Deploy for custom domains and canaries.
Next steps
- Auth — add sign-in and row-level security
- Realtime — live updates as rows change
- SDK reference · Database