SDK
The SDK is the fastbase-sdk package on npm (npm install fastbase-sdk; inside this repository @fastbase/sdk), a zero-dependency TypeScript client. It uses the platform’s fetch and WebSocket, so the same code runs in browsers, Node.js 22+, Deno, Bun and edge runtimes.
import { createFastBase } from "fastbase-sdk"
const fastbase = createFastBase({
url: process.env.FASTBASE_URL!,
key: process.env.FASTBASE_PUBLIC_KEY!,
})
FASTBASE injects FASTBASE_URL, FASTBASE_PUBLIC_KEY, FASTBASE_SECRET_KEY and FASTBASE_REALTIME_URL into every deployed app. For browser code, reference NEXT_PUBLIC_FASTBASE_URL / NEXT_PUBLIC_FASTBASE_PUBLIC_KEY (or the VITE_ equivalents) in your .env.example and FASTBASE fills them in too. The secret key is never exposed through a public prefix.
Two keys
| Key | Where | Can do |
|---|---|---|
Public (fbpk_…) |
Browsers, mobile apps | Sign users in, read public buckets, call functions, use realtime, manage a signed-in user’s own files |
Secret (fbsk_…) |
Servers only | Everything, including tables and all files |
The SDK refuses to start with a secret key in a browser.
Errors
Every method throws FastBaseError with code, status and requestId:
try {
await fastbase.auth.signIn({ email, password })
} catch (error) {
if (error instanceof FastBaseError && error.code === "INVALID_CREDENTIALS") { /* … */ }
}
Auth
await fastbase.auth.signUp({ email, password, metadata: { plan: "pro" } })
const { user, session } = await fastbase.auth.signInWithEmail({ email, password })
await fastbase.auth.signInWithOtp({ phone: "+905551234567" })
await fastbase.auth.verifyOtp({ phone: "+905551234567", code: "123456" })
await fastbase.auth.signInAnonymously()
const current = await fastbase.auth.getUser() // null when signed out
await fastbase.auth.signOut()
The session lives in memory. Persist session yourself (cookie, secure storage) and restore it with fastbase.auth.setSession(session). On a server, verify a user’s token the same way: setSession(...) then getUser().
Database
Server-side, with the secret key:
const users = await fastbase.from("users").select()
const adults = await fastbase
.from("users")
.select("id,name")
.gte("age", 18)
.order("name")
.limit(20)
await fastbase.from("users").insert({ name: "Ada" })
await fastbase.from("users").update({ age: 37 }).eq("name", "Ada")
await fastbase.from("users").delete().eq("id", 1)
const first = await fastbase.from("users").select().eq("id", 1).first()
Filters: eq, neq, gt, gte, lt, lte, like, ilike, in, isNull, notNull. update and delete require at least one filter.
FASTBASE has no row-level security yet, so tables are never reachable with the public key. Put data access behind your own server routes or functions.
Storage
await fastbase.storage.bucket("avatars").upload("user.png", file)
const url = await fastbase.storage.bucket("avatars").getPublicUrl("user.png")
const blob = await fastbase.storage.bucket("docs").download("contract.pdf")
const link = await fastbase.storage.bucket("docs").createSignedUrl("contract.pdf", 3600)
await fastbase.storage.bucket("docs").remove("contract.pdf")
See Storage for who may read and write what.
Functions
const result = await fastbase.functions.invoke("send-welcome-email", { userId })
Realtime
const room = fastbase
.channel("room:123")
.on("message", ({ payload }) => render(payload))
.onPresence((event) => updateOnline(event))
await room.subscribe()
room.send("message", { text: "Hello" })
room.track({ typing: true })
See Realtime.