cli
SpacetimeDB CLI reference for initializing projects, building modules, publishing databases, querying data, and managing servers
SpacetimeDB TypeScript/React client SDK reference. Use when building web clients that connect to SpacetimeDB.
Claude Code
$ npx -y skills add clockworklabs/spacetimedb --skill typescript-client --agent claude-code
Codex
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a codex -y
Cursor
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a cursor -y
Gemini CLI
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a gemini-cli -y
GitHub Copilot
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a github-copilot -y
OpenCode
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a opencode -y
Windsurf
$ npx skills add clockworklabs/spacetimedb --skill typescript-client -a windsurf -y
name: typescript-client description: SpacetimeDB TypeScript/React client SDK reference. Use when building web clients that connect to SpacetimeDB. license: Apache-2.0 metadata: author: clockworklabs version: "2.0" role: client language: typescript cursor_globs: "**/*.tsx,**/*.ts" cursor_always_apply: true
Generated bindings convert snake_case names to camelCase, including row fields: a server column `trip_id` is `tripId` on client rows.
import React, { useMemo } from 'react';
import ReactDOM from 'react-dom/client';
import { SpacetimeDBProvider } from 'spacetimedb/react';
import { DbConnection } from './module_bindings';
import { MODULE_NAME, SPACETIMEDB_URI } from './config';
import App from './App';
const TOKEN_KEY = `${SPACETIMEDB_URI}/${MODULE_NAME}/auth_token`;
function Root() {
const connectionBuilder = useMemo(() =>
DbConnection.builder()
.withUri(SPACETIMEDB_URI)
.withDatabaseName(MODULE_NAME)
.withToken(localStorage.getItem(TOKEN_KEY) ?? undefined)
.withAutomaticReconnect()
.onConnect((_conn, _identity, token) => localStorage.setItem(TOKEN_KEY, token)),
[]
);
return (
<SpacetimeDBProvider connectionBuilder={connectionBuilder}>
<App />
</SpacetimeDBProvider>
);
}
ReactDOM.createRoot(document.getElementById('root')!).render(<Root />);import { useTable, useSpacetimeDB } from 'spacetimedb/react';
import { DbConnection, tables } from './module_bindings';
export default function App() {
const { isActive, identity: myIdentity, getConnection } = useSpacetimeDB();
const conn = getConnection() as DbConnection | null;
// useTable owns subscriptions and reports readiness after replay.
const [entities, entitiesReady] = useTable(tables.entity);
const [records, recordsReady] = useTable(tables.record);
const [onlineUsers] = useTable(
tables.entity.where(r => r.active.eq(true)),
{
onInsert: user => console.log('User connected:', user.name),
onDelete: user => console.log('User disconnected:', user.name),
onUpdate: (oldUser, newUser) => console.log('Updated:', newUser.name),
}
);
const addRecord = (data: string) => {
if (!conn || !isActive) return;
void conn.reducers.addRecord({ data }).catch(console.error);
};
const ownsEntity = entities.some(
row => row.owner.toHexString() === myIdentity?.toHexString()
);
return (
<main>
<p>{isActive ? 'Connected' : 'Not connected'}</p>
<p>{entitiesReady && recordsReady ? 'Data ready' : 'Waiting for current data'}</p>
<p>{onlineUsers.length} users online, {records.length} records</p>
<p>{ownsEntity ? 'You own an entity' : 'No owned entity'}</p>
<button disabled={!isActive} onClick={() => addRecord('Hello!')}>
Add record
</button>
</main>
);
}import { DbConnection, tables } from './module_bindings';
const HOST = 'wss://maincloud.spacetimedb.com';
const DATABASE = 'my_module';
const TOKEN_KEY = `${HOST}/${DATABASE}/auth_token`;
const conn = DbConnection.builder()
.withUri(HOST)
.withDatabaseName(DATABASE)
.withToken(localStorage.getItem(TOKEN_KEY) ?? undefined)
.withAutomaticReconnect()
.onConnect((_conn, identity, token) => {
localStorage.setItem(TOKEN_KEY, token);
console.log('Connected as:', identity.toHexString());
})
.onDisconnect((_ctx, error, nextAttempt, delayMs) => {
if (nextAttempt !== undefined) {
console.warn(`Reconnect attempt ${nextAttempt} in ${delayMs} ms`, error);
} else {
console.log('Connection ended', error);
}
})
.onConnectError((_ctx, error, nextAttempt, delayMs) => {
console.error('Connection failed:', error);
if (nextAttempt !== undefined) {
console.log(`Retry ${nextAttempt} in ${delayMs} ms`);
}
})
.build();
// Register once; the SDK replays this subscription after reconnecting.
const subscription = conn.subscriptionBuilder()
.onApplied(() => console.log('Ready'))
.subscribe([tables.user, tables.message]);
// Row callbacks
conn.db.user.onInsert((ctx, user) => console.log('Joined:', user.name));
conn.db.user.onDelete((ctx, user) => console.log('Left:', user.name));
conn.db.user.onUpdate((ctx, oldUser, newUser) => console.log('Updated:', newUser.name));Generated bindings preserve submodule accessors as nested members. For a namespace accessor `myAuth` pinned to canonical `auth_data`:
conn.subscriptionBuilder().subscribe([tables.myAuth.users]);
// Rows: conn.db.myAuth.users
// Reducers: conn.reducers.myAuth.verifyToken({ token: 'example' })
// React: useTable(tables.myAuth.users), useReducer(reducers.myAuth.verifyToken)Use generated accessors in SDK calls; they encode canonical names automatically. Raw SQL/HTTP/CLI calls instead use canonical qualified names such as `auth_data.users` or `auth_data.verify_token`. Namespaces share the connection and cache; they are not separate database connections.
For views with arguments (2.13+), use a raw SQL subscription; TypeScript has no typed argument-bearing view query builder yet:
conn.subscriptionBuilder().subscribe('SELECT * FROM by_id(42)');Use explicit queries for every table on that connection, not subscribe-all, which skips views with arguments. Only `SELECT * FROM view_name(literal_args)` is supported. All argument values share one cache table; unsubscribe from obsolete arguments to avoid combining their rows. Validate/encode dynamic values as SQL literals rather than concatenating untrusted input. In React, raw SQL subscriptions need explicit lifetime management and cleanup; `useTable` does not supply an argument-bearing view builder.
The React provider's connection manager enables automatic reconnect; the explicit `.withAutomati
SpacetimeDB CLI reference for initializing projects, building modules, publishing databases, querying data, and managing servers
Understand SpacetimeDB architecture and core concepts. Use when learning SpacetimeDB or making architectural decisions.
SpacetimeDB C++ server module SDK reference. Use when writing tables, reducers, or module logic in C++.
SpacetimeDB C#/.NET client SDK reference. Use when building C# clients that connect to SpacetimeDB (console, desktop, or any .NET…
SpacetimeDB C# server module SDK reference. Use when writing tables, reducers, or module logic in C#.
Operate a running SpacetimeDB database through MCP tools rather than the CLI - list databases, read schemas, run SQL, and call…
Best practices for implementing JWT, API Keys, OAuth 2.1, and RBAC in a NitroStack application.