Migrating From Native SDK Shape
The Same Module, Both Ways
Section titled “The Same Module, Both Ways”The native module and the equivalent effect-spacetimedb contract — declare the shape, then implement handlers behind the typed group:
import { schema, table, t } from "spacetimedb/server"
const spacetime = schema({ user: table( { public: true }, { id: t.string().primaryKey(), name: t.string() }, ),})
export const user_upsert = spacetime.reducer( "user_upsert", { id: t.string(), name: t.string() }, (ctx, { id, name }) => { ctx.db.user.insert({ id, name }) },)
export default spacetimeimport * as Effect from "effect/Effect"import * as Stdb from "effect-spacetimedb"
// 1. declare the contractconst user = Stdb.table("user", { public: true, columns: { id: Stdb.string().primaryKey(), name: Stdb.string(), },})
const Users = Stdb.StdbGroup.make("Users").add( Stdb.StdbFn.reducer("user_upsert", { params: Stdb.struct({ id: Stdb.string(), name: Stdb.string() }), }),)
const Module = Stdb.StdbModule.make("app").addTables(user).add(Users)const { Db } = Module
// 2. implement handlers behind the typed groupconst UsersLive = Stdb.StdbBuilder.group(Module, "Users", { user_upsert: (args) => Effect.gen(function* () { const db = yield* Db yield* db.user.insert(args) }),})Native Shape To Contract Shape
Section titled “Native Shape To Contract Shape”| Native concept | effect-spacetimedb concept |
|---|---|
| reducer function export | StdbFn.reducer(...) in a callable group |
| procedure function export | StdbFn.procedure(...) in a callable group |
| table builder | Stdb.table(...) bound to a variable |
| scheduled table callback | StdbFn.scheduledReducer(...) or scheduledProcedure(...) |
| HTTP handler export | StdbHttpGroup plus StdbBuilder.group(...) |
Suggested Order
Section titled “Suggested Order”- Move schemas and table declarations into leaf files.
- Declare groups without changing runtime behavior.
- Assemble a module and destructure the typed accessors.
- Port handlers one group at a time.
- Generate the client and replace ad hoc call sites with projected clients.
Keep the runtime constraints in mind: module handlers must remain synchronous, deterministic, and transactional. Network calls, timers, and secrets belong outside reducers and are passed in as arguments or handled by external services.
Not affiliated with SpacetimeDB (Clockwork Laboratories) or Effect (Effectful Technologies).