Deno Quickstart
Get a SpacetimeDB Deno app running in under 5 minutes.
Prerequisites
- Deno installed
- SpacetimeDB CLI installed
Run the spacetime dev command to create a new project with a SpacetimeDB module and Deno client.
This will start the local SpacetimeDB server, publish your module, and generate TypeScript bindings.
spacetime dev --template deno-tsYour project contains both server and client code.
Edit spacetimedb/src/index.ts to add tables and reducers. Edit src/main.ts to build your Deno client.
my-spacetime-app/
├── spacetimedb/ # Your SpacetimeDB module
│ └── src/
│ └── index.ts # Server-side logic
├── src/
│ ├── main.ts # Deno client script
│ └── module_bindings/ # Auto-generated types
└── package.json # Scripts and dependencies (dev, start, spacetime:generate)
Open spacetimedb/src/index.ts to see the module code. The template includes a person table and two reducers: add to insert a person, and say_hello to greet everyone.
Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
import { schema, table, t } from 'spacetimedb/server';
export const spacetimedb = schema(
table(
{ name: 'person', public: true },
{
name: t.string(),
}
)
);
spacetimedb.reducer('add', { name: t.string() }, (ctx, { name }) => {
ctx.db.person.insert({ name });
});
spacetimedb.reducer('say_hello', ctx => {
for (const person of ctx.db.person.iter()) {
console.info(`Hello, ${person.name}!`);
}
console.info('Hello, World!');
});In a new terminal, run the Deno client. It will connect to SpacetimeDB and start an interactive CLI where you can add people and query the database.
# Run with auto-reload during development
pnpm run dev
# or: npm run dev
# Or run once
pnpm run start
# or: npm run startThe client provides a command-line interface to interact with your SpacetimeDB module. Type a name to add a person, or use the built-in commands.
Connecting to SpacetimeDB...
URI: ws://localhost:3000
Module: deno-ts
Connected to SpacetimeDB!
Identity: abc123def456...
Current people (0):
(none yet)
Commands:
<name> - Add a person with that name
list - Show all people
hello - Greet everyone (check server logs)
Ctrl+C - Quit
> Alice
> [Added] Alice
> Bob
> [Added] Bob
> list
> People in database:
- Alice
- Bob
> hello
> Called say_hello reducer (check server logs)
Open src/main.ts to see the Deno client. It uses DbConnection.builder() to connect to SpacetimeDB, subscribes to tables, and sets up the interactive CLI using Deno's native APIs.
Unlike browser apps, Deno stores the authentication token in a file using Deno.readTextFile() and Deno.writeTextFile().
import { DbConnection } from './module_bindings/index.ts';
// Build and establish connection
DbConnection.builder()
.withUri(HOST)
.withModuleName(DB_NAME)
.withToken(await loadToken()) // Load saved token from file
.onConnect((conn, identity, token) => {
console.log('Connected! Identity:', identity.toHexString());
saveToken(token); // Save token for future connections
// Subscribe to all tables
conn.subscriptionBuilder()
.onApplied((ctx) => {
// Show current data, start CLI
setupCLI(conn);
})
.subscribeToAllTables();
// Listen for table changes
conn.db.person.onInsert((ctx, person) => {
console.log(`[Added] ${person.name}`);
});
})
.build();You can also use the SpacetimeDB CLI to call reducers and query your data directly. Changes made via the CLI will appear in your Deno client in real-time.
# Call the add reducer to insert a person
spacetime call add Charlie
# Query the person table
spacetime sql "SELECT \* FROM person"
name
---
"Alice"
"Bob"
"Charlie"
# Call say_hello to greet everyone
spacetime call say_hello
# View the module logs
spacetime logs
2025-01-13T12:00:00.000000Z INFO: Hello, Alice!
2025-01-13T12:00:00.000000Z INFO: Hello, Bob!
2025-01-13T12:00:00.000000Z INFO: Hello, Charlie!
2025-01-13T12:00:00.000000Z INFO: Hello, World!
Permissions: Deno requires explicit permissions. The template uses --allow-net for WebSocket connections, --allow-read and --allow-write for token persistence, and --allow-env for configuration.
Sloppy imports: The --unstable-sloppy-imports flag is required because the generated module bindings use extensionless imports (Node.js convention), while Deno requires explicit file extensions. This flag enables Node.js-style module resolution.
Built-in TypeScript: Deno runs TypeScript directly without transpilation, making startup faster and eliminating the need for build tools.
Dependencies: The package.json file declares the spacetimedb dependency; Deno resolves it from there (and from node_modules after pnpm install when developing in the SpacetimeDB repo).
node_modules: When using the template from the repo workspace, run pnpm install so spacetimedb is linked. For a project created with spacetime init, Deno resolves the versioned dependency from package.json.
# Configure via environment variables
SPACETIMEDB_HOST=ws://localhost:3000 \
SPACETIMEDB_DB_NAME=my-app \
pnpm run start
# Or run with explicit permissions
deno run --allow-net --allow-read --allow-write --allow-env --unstable-sloppy-imports src/main.ts
# package.json defines scripts and the spacetimedb dependency
cat package.json
{
"scripts": {
"dev": "deno run --watch --allow-net --allow-read --allow-write --allow-env --unstable-sloppy-imports src/main.ts",
"start": "deno run --allow-net --allow-read --allow-write --allow-env --unstable-sloppy-imports src/main.ts",
"spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb"
},
"dependencies": {
"spacetimedb": "workspace:*"
}
}Next steps
- See the Chat App Tutorial for a complete example
- Read the TypeScript SDK Reference for detailed API docs