| Crates.io | supabase-client-rs |
| lib.rs | supabase-client-rs |
| version | 0.1.0 |
| created_at | 2025-12-02 16:22:36.597774+00 |
| updated_at | 2025-12-02 16:22:36.597774+00 |
| description | A unified Rust client for Supabase with database, realtime, auth, storage, and functions support |
| homepage | https://github.com/Scaraude/supabase-client-rs |
| repository | https://github.com/Scaraude/supabase-client-rs |
| max_upload_size | |
| id | 1962120 |
| size | 110,656 |
A unified Rust client for Supabase, the open-source Firebase alternative.
This crate provides a unified interface to Supabase services by composing existing community crates:
| Service | Status | Crate |
|---|---|---|
| Database (PostgREST) | ✅ Ready | postgrest-rs |
| Realtime | ✅ Ready | supabase-realtime-rs |
| Auth | 📦 Trait defined | Community: TBD |
| Storage | 📦 Trait defined | Community: TBD |
| Edge Functions | 📦 Trait defined | Community: TBD |
cargo add supabase-client-rs
use supabase_client_rs::create_client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = create_client(
"https://your-project.supabase.co",
"your-anon-key"
)?;
// Query the database
let response = client
.from("users")
.select("id, name, email")
.eq("active", "true")
.limit(10)
.execute()
.await?;
let users: Vec<serde_json::Value> = response.json().await?;
println!("{:?}", users);
Ok(())
}
The client wraps postgrest-rs for all database operations:
// Select with filters
let users = client
.from("users")
.select("*")
.eq("status", "active")
.order("created_at.desc")
.limit(10)
.execute()
.await?;
// Insert
let new_user = client
.from("users")
.insert(r#"{"name": "Alice", "email": "alice@example.com"}"#)
.execute()
.await?;
// Update
let updated = client
.from("users")
.update(r#"{"status": "inactive"}"#)
.eq("id", "123")
.execute()
.await?;
// Delete
let deleted = client
.from("users")
.delete()
.eq("id", "123")
.execute()
.await?;
// RPC (stored procedures)
let result = client
.rpc("get_user_stats", r#"{"user_id": "123"}"#)
.execute()
.await?;
use supabase_client_rs::{SupabaseClient, SupabaseConfig};
use std::time::Duration;
let config = SupabaseConfig::new(
"https://your-project.supabase.co",
"your-anon-key"
)
.schema("custom_schema")
.timeout(Duration::from_secs(60))
.header("X-Custom-Header", "value");
let client = SupabaseClient::with_config(config)?;
After a user signs in, set their JWT for Row Level Security:
// Get JWT from your auth flow
let user_jwt = "eyJhbGciOiJIUzI1NiIs...";
// Create an authenticated client
let auth_client = client.with_jwt(user_jwt)?;
// Requests now include the user's JWT
// RLS policies will apply based on the user
Enable the realtime feature to use Supabase Realtime:
cargo add supabase-client-rs --features "realtime"
Then use the realtime client:
use supabase_realtime_rs::{ChannelEvent, RealtimeChannelOptions};
// Get the realtime client
let realtime = client.realtime();
// Connect to realtime
realtime.connect().await?;
// Subscribe to a channel
let channel = realtime.channel("room:lobby", RealtimeChannelOptions::default()).await;
let mut rx = channel.on(ChannelEvent::broadcast("message")).await;
channel.subscribe().await?;
// Send a message
channel.send(
ChannelEvent::broadcast("message"),
serde_json::json!({"text": "Hello from Rust!"})
).await?;
// Listen for messages
tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
println!("Received: {:?}", msg);
}
});
See examples/realtime.rs for a complete example including presence tracking and database changes.
Contributions are welcome! Areas that need work:
supabase-realtime-rsAuthProvider traitStorageProvider traitFunctionsProvider traitSee the traits module for the interfaces to implement.
This project builds on the excellent work of: