Client SDK — Getting Started
Overview
Section titled “Overview”The @rebasepro/client package provides a type-safe JavaScript SDK for interacting with your Rebase backend. It handles:
- Data operations — CRUD with filtering, sorting, and pagination
- Relation fetching — Include related entities with
.include() - Real-time subscriptions — WebSocket-based live updates
- Offline & local-first sync — Opt-in local row database, instant offline writes, live queries
- Authentication — Token management, login, signup, OAuth
- Storage — File upload, download, and management
- Custom functions — Call custom server endpoints
Installation
Section titled “Installation”pnpm add @rebasepro/clientCreating a Client
Section titled “Creating a Client”import { createRebaseClient } from "@rebasepro/client";
const client = createRebaseClient({ baseUrl: "http://localhost:3001",});The websocketUrl is derived automatically from baseUrl (http → ws, https → wss). You can override it explicitly if needed:
const client = createRebaseClient({ baseUrl: "http://localhost:3001", websocketUrl: "ws://localhost:3001",});Configuration Options
Section titled “Configuration Options”| Option | Type | Description |
|---|---|---|
baseUrl |
string |
Backend URL (e.g. http://localhost:3001) |
websocketUrl |
string |
WebSocket URL — auto-derived from baseUrl if omitted |
token |
string |
Static JWT token for server-to-server calls |
apiPath |
string |
API prefix (default: "/api") |
fetch |
typeof fetch |
Custom fetch implementation (e.g. for SSR) |
onUnauthorized |
() => Promise<boolean> |
Custom 401 handler — return true to retry |
realtime |
boolean |
Open the WebSocket (default true) — set false in one-shot scripts |
collections |
Record<string, string> |
Maps accessor names to collection slugs |
offline |
boolean | OfflineConfig |
Local-first sync — off by default |
Typed SDK Generation
Section titled “Typed SDK Generation”Generate a fully typed client from your collection definitions:
rebase generate-sdkThen pass the Database type parameter to createRebaseClient for full autocomplete:
import { createRebaseClient } from "@rebasepro/client";import { collectionsDictionary, type Database } from "./generated/sdk/database.types";
const client = createRebaseClient<Database>({ baseUrl: "http://localhost:3001", collections: collectionsDictionary,});
// Full autocomplete on collection names and field typesconst { data } = await client.data.products.find();When Database is supplied, createRebaseClient returns a CreateRebaseClientResult<DB> instance. This maps camelCase collection accessors directly on client.data to their corresponding types, giving you full autocomplete on collection operations and types (e.g. client.data.products.find()).
collectionsDictionary maps each accessor back to the slug the wire uses. Pass it whenever a slug is not already a valid property name — my-notes is reachable as client.data.myNotes only because the dictionary says so.
Field names
Section titled “Field names”A field’s name on the wire is its property key, and the API is camelCase throughout. A createdAt property stored in a created_at column is row.createdAt, and a relation’s foreign key is authorId even though the column stays author_id. where and orderBy are keyed off the same Row type, so what compiles is what the backend answers to.
A property key you wrote is your key, whatever its shape — nothing renames a name you chose. The two keys that are derived rather than declared, a relation’s foreign key and a column read back by introspection, are camelCase.
Row describes a read, Insert a create() and Update an update() — they are not the same shape. Nullable columns are T | null on Row, the primary key is always present on a read and never settable on an update, and a belongsTo target can be written either as the relation ({ author: 5 }) or as its foreign key ({ authorId: 5 }).
Quick Example
Section titled “Quick Example”// Createconst product = await client.data.products.create({ name: "Camera", price: 299,});
// Query with filtersconst { data } = await client.data.products .where("price", ">=", 100) .orderBy("createdAt", "desc") .limit(10) .find();
// Real-time subscriptionconst unsubscribe = client.data.products.listen( { where: { active: ["==", true] } }, (response) => console.log("Updated:", response.data));Using with React
Section titled “Using with React”In a Rebase frontend, the client is created once and shared via context:
import { createRebaseClient } from "@rebasepro/client";
const client = createRebaseClient({ baseUrl: API_URL });
<Rebase client={client} ...>Access it from any component:
import { useRebaseClient } from "@rebasepro/app";
function MyComponent() { const client = useRebaseClient(); // client.data, client.auth, client.storage, client.functions}Next Steps
Section titled “Next Steps”- Querying Data — CRUD, filters, pagination, and relations
- Authentication — Sign in, sign up, OAuth, sessions
- Realtime Subscriptions — Live data with WebSockets
- Offline & Local-First Sync — Work without a connection, and sync when it returns
- Storage & Files — Upload, download, and manage files
