Skip to content
Development
Skill

/typescript-client

SpacetimeDB TypeScript/React client SDK reference. Use when building web clients that connect to SpacetimeDB.

From plugin
spacetimedb
25k22 skills1 MCP
Install
$ npx -y skills add clockworklabs/spacetimedb --skill typescript-client --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/typescript-client

Context preview

The summary Claude sees to decide when to auto-load this skill.

SpacetimeDB TypeScript/React client SDK reference. Use when building web clients that connect to SpacetimeDB.

SKILL.md

typescript-client.SKILL.md
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

SpacetimeDB TypeScript Client

Generated bindings convert snake_case names to camelCase, including row fields: a server column `trip_id` is `tripId` on client rows.

React: main.tsx

import React, { useEffect, 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';

function Root() {
  const connectionBuilder = useMemo(() =>
    DbConnection.builder()
      .withUri(SPACETIMEDB_URI)
      .withDatabaseName(MODULE_NAME)
      .withToken(localStorage.getItem('auth_token') || undefined),
    []
  );
  return (
    <SpacetimeDBProvider connectionBuilder={connectionBuilder}>
      <App />
    </SpacetimeDBProvider>
  );
}

ReactDOM.createRoot(document.getElementById('root')!).render(<Root />);

React: App.tsx

import { useTable, useSpacetimeDB } from 'spacetimedb/react';
import { DbConnection, tables } from './module_bindings';

function App() {
  const { isActive, identity: myIdentity, token, getConnection } = useSpacetimeDB();
  const conn = getConnection() as DbConnection | null;

  // Save auth token
  useEffect(() => { if (token) localStorage.setItem('auth_token', token); }, [token]);

  // Subscribe when connected. Prefer typed query builders over raw SQL
  useEffect(() => {
    if (!conn || !isActive) return;
    conn.subscriptionBuilder()
      .onApplied(() => setSubscribed(true))
      .subscribe([tables.entity, tables.record]);
      // Or with filters: tables.entity.where(r => r.active.eq(true))
      // Or raw SQL:      'SELECT * FROM entity'
  }, [conn, isActive]);

  // Reactive data. Returns [rows, isReady]
  const [entities, entitiesReady] = useTable(tables.entity);
  const [records, recordsReady] = useTable(tables.record);

  // useTable with row callbacks
  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),
    }
  );

  // Call reducers with object syntax
  conn?.reducers.addRecord({ data }).catch(console.error);

  // Compare identities
  const isMe = row.owner.toHexString() === myIdentity?.toHexString();
}

Vanilla (non-React)

import { DbConnection, tables } from './module_bindings';

const conn = DbConnection.builder()
  .withUri('wss://maincloud.spacetimedb.com')
  .withDatabaseName('my_module')
  .onConnect((ctx) => {
    ctx.subscriptionBuilder()
      .onApplied(() => console.log('Ready'))
      .subscribe([tables.user, tables.message]);
  })
  .build();

// 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));

Gotchas

  • **`useTable` rows are `readonly`.** Copy before sorting/mutating, or it fails to type-check:

`const [rows] = useTable(tables.message); const sorted = [...rows].sort(...)`.

  • **bigint in JSX.** ids/counts from `t.u64()`/`t.i64()` columns are `bigint`, which React

cannot render. Wrap it: `{Number(row.id)}` or `{String(count)}`.

Read more
Ships withspacetimedb

Development at the speed of light

Get the whole plugin
Stats
24,990
Stars
1,035
Forks
Active
Maintenance
Rust
Language
1h ago
Last commit
3y ago
Created

Repo: clockworklabs/spacetimedb