SpacetimeDB Best Practices
Comprehensive development guide for SpacetimeDB applications, covering both TypeScript server modules and client SDK integration with React. Contains rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
Package: spacetimedb (v1.4.0+)
When to Apply
Reference these guidelines when:
- •Writing SpacetimeDB server modules in TypeScript
- •Designing table schemas and indexes
- •Implementing reducers for state mutations
- •Setting up client subscriptions and queries
- •Integrating SpacetimeDB with React applications
- •Optimizing real-time sync performance
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Module Design | CRITICAL | module- |
| 2 | Table Schema & Indexing | CRITICAL | table- |
| 3 | Reducer Patterns | HIGH | reducer- |
| 4 | Subscription Optimization | HIGH | subscription- |
| 5 | Client State Management | MEDIUM-HIGH | client- |
| 6 | React Integration | MEDIUM | react- |
| 7 | TypeScript Patterns | MEDIUM | ts- |
| 8 | Real-time Sync | LOW-MEDIUM | sync- |
Quick Reference
Server Module API (TypeScript)
typescript
import { spacetimedb, table, t, ReducerContext } from 'spacetimedb';
// Define tables with the table builder
const Player = table(
{ name: 'player', public: true },
{
identity: t.identity().primaryKey(),
name: t.string(),
score: t.u64().index(),
isOnline: t.bool().index(),
}
);
// Define reducers
spacetimedb.reducer('create_player', { name: t.string() }, (ctx: ReducerContext, { name }) => {
ctx.db.player.insert({
identity: ctx.sender,
name,
score: 0n,
isOnline: true,
});
});
// Lifecycle hooks
spacetimedb.init((ctx: ReducerContext) => { /* module init */ });
spacetimedb.clientConnected((ctx: ReducerContext) => { /* client connected */ });
spacetimedb.clientDisconnected((ctx: ReducerContext) => { /* client disconnected */ });
Client SDK API (TypeScript)
typescript
import { DbConnection } from './generated';
// Build connection
const conn = DbConnection.builder()
.withUri('ws://localhost:3000')
.withModuleName('my-module')
.onConnect((ctx, identity, token) => {
// Setup subscriptions
conn.subscription(['SELECT * FROM player WHERE isOnline = true']);
})
.onDisconnect((ctx, error) => { /* handle disconnect */ })
.build();
// Call reducers
await conn.reducers.createPlayer('Alice');
// Access tables
const player = conn.db.player.identity.find(identity);
React Integration
typescript
import { useTable, where, eq } from 'spacetimedb/react';
import { DbConnection, Player } from './generated';
function OnlinePlayers() {
const { rows: players } = useTable<DbConnection, Player>(
'player',
where(eq('isOnline', true))
);
return players.map(p => <div key={p.identity.toHexString()}>{p.name}</div>);
}
Rule Categories
1. Module Design (CRITICAL)
- •
module-single-responsibility- One module per domain concept - •
module-lifecycle- Use lifecycle hooks appropriately (init, clientConnected, clientDisconnected) - •
module-error-handling- Handle errors gracefully in module code - •
module-type-exports- Export types for client consumption
2. Table Schema & Indexing (CRITICAL)
- •
table-primary-keys- Choose appropriate primary key strategies - •
table-indexing- Add.index()for frequently queried columns - •
table-relationships- Model relationships between tables correctly - •
table-column-types- Use appropriate SpacetimeDB types
3. Reducer Patterns (HIGH)
- •
reducer-atomicity- Keep reducers atomic and focused - •
reducer-validation- Validate inputs at reducer entry - •
reducer-authorization- Check caller identity for sensitive operations - •
reducer-batch-operations- Batch related mutations in single reducer
4. Subscription Optimization (HIGH)
- •
subscription-selective- Subscribe only to needed data - •
subscription-filters- Use subscription filters to reduce data transfer - •
subscription-cleanup- Clean up subscriptions when no longer needed - •
subscription-batching- Batch subscription setup on client connect
5. Client State Management (MEDIUM-HIGH)
- •
client-connection-lifecycle- Handle connection/reconnection properly - •
client-optimistic-updates- Use optimistic updates for responsive UI - •
client-error-recovery- Handle reducer errors gracefully - •
client-identity- Manage identity tokens securely
6. React Integration (MEDIUM)
- •
react-use-subscription- Use subscription hooks correctly - •
react-table-hooks- UseuseTable<DbConnection, Type>()for reactive data - •
react-reducer-hooks- Callconn.reducers.*with proper error handling - •
react-connection-status- Display connection status to users
7. TypeScript Patterns (MEDIUM)
- •
ts-generated-types- Use generated types from SpacetimeDB CLI - •
ts-strict-mode- Enable strict TypeScript for better type safety - •
ts-discriminated-unions- Use discriminated unions for state - •
ts-type-guards- Implement type guards for runtime validation
8. Real-time Sync (LOW-MEDIUM)
- •
sync-conflict-resolution- Handle concurrent modifications - •
sync-offline-support- Design for offline-first when needed - •
sync-debounce-updates- Debounce rapid UI updates - •
sync-presence- Implement user presence efficiently
How to Use
Read individual rule files for detailed explanations and code examples:
code
rules/module-single-responsibility.md rules/table-primary-keys.md rules/_sections.md
Each rule file contains:
- •Brief explanation of why it matters
- •Incorrect code example with explanation
- •Correct code example with explanation
- •Additional context and references
Full Compiled Document
For the complete guide with all rules expanded: AGENTS.md