Migrate from Supabase
ZendBX is designed to be familiar to Supabase users. Most of the API is identical. Migration typically takes less than an hour.
Client Initialization
typescriptBefore (Supabase)
// Supabase
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);typescriptAfter (ZendBX)
// ZendBX
import { createClient } from '@zendbx/sdk';
const db = createClient({
apiUrl: ZENDBX_URL,
anonKey: ZENDBX_ANON_KEY,
projectSlug: 'my-project',
});Authentication
typescript
// Supabase
const { data } = await supabase.auth.signInWithPassword({ email, password });
// ZendBX (identical API)
const { data } = await db.auth.signIn({ email, password });
// Also available: db.auth.signInWithPassword({ email, password })💡ZendBX auth is project-scoped. Each project has its own user table and JWT secret.
Database
typescript
// Supabase
const { data } = await supabase.from('todos').select('*').eq('done', false);
// ZendBX (identical API)
const { data } = await db.from('todos').select('*').eq('done', false);The query builder is nearly identical. All filter methods work the same way.
Storage
typescript
// Supabase
await supabase.storage.from('avatars').upload('user.png', file);
// ZendBX ← note: .bucket() not .from()
await db.storage.bucket('avatars').upload(file, 'user.png');⚠️The main difference: ZendBX uses
.bucket(slug) instead of .from(bucket). Upload argument order also differs: ZendBX takes (file, filename) instead of (path, file).Migration Checklist
- □Replace @supabase/supabase-js with @zendbx/sdk
- □Update createClient() call to use options object with projectSlug
- □Replace .storage.from() with .storage.bucket()
- □Update upload() call argument order
- □Move environment variables from SUPABASE_* to ZENDBX_*
- □Create an equivalent project in the ZendBX dashboard
- □Run any existing SQL migrations against the new project schema

