diff --git a/templates/angular-ts/.template.json b/templates/angular-ts/.template.json
index 06c3ea9a227..5d54f7d2eff 100644
--- a/templates/angular-ts/.template.json
+++ b/templates/angular-ts/.template.json
@@ -2,5 +2,12 @@
"description": "Angular web app with TypeScript server",
"client_framework": "Angular",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "angular",
+ "rxjs",
+ "tslib",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/angular-ts/README.md b/templates/angular-ts/README.md
new file mode 100644
index 00000000000..2dcdcc7241c
--- /dev/null
+++ b/templates/angular-ts/README.md
@@ -0,0 +1,117 @@
+Get a SpacetimeDB Angular app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Angular client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Angular development server.
+
+```bash
+spacetime dev --template angular-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:4200](http://localhost:4200) to see your app running.
+
+The template includes a basic Angular app connected to SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/app/app.component.ts` to build your UI.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/ # Angular frontend
+│ └── app/
+│ ├── app.component.ts
+│ ├── app.config.ts
+│ └── module_bindings/ # Auto-generated types
+├── angular.json
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+## Next steps
+
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/basic-cpp/.template.json b/templates/basic-cpp/.template.json
index 983a1b065ff..cabcda719fe 100644
--- a/templates/basic-cpp/.template.json
+++ b/templates/basic-cpp/.template.json
@@ -1,5 +1,8 @@
{
"description": "A basic C++ server template with only stubs for code",
"server_lang": "cpp",
- "client_lang": "rust"
+ "client_lang": "rust",
+ "builtWith": [
+ "spacetimedb-sdk"
+ ]
}
diff --git a/templates/basic-cpp/README.md b/templates/basic-cpp/README.md
new file mode 100644
index 00000000000..4e122dc0e94
--- /dev/null
+++ b/templates/basic-cpp/README.md
@@ -0,0 +1,118 @@
+Get a SpacetimeDB C++ app running in under 5 minutes.
+
+## Prerequisites
+
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+- [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) 4.0.21+ installed
+- CMake 3.20+ and a make/ninja backend
+- C++20 toolchain (host) — build targets WASM via Emscripten
+
+After installing the SDK, run the appropriate `emsdk_env` script (PowerShell or Bash) so `emcc` and the CMake toolchain file are available on `PATH`.
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Install Emscripten
+
+Use the official SDK (see [Emscripten downloads](https://emscripten.org/docs/getting_started/downloads.html)) and activate the environment so `emcc` and the CMake toolchain file are on PATH. We recommend Emscripten 4.0.21+.
+
+```bash
+# From your emsdk directory (after downloading/cloning)
+# Windows PowerShell
+./emsdk install 4.0.21
+./emsdk activate 4.0.21
+./emsdk_env.ps1
+
+# macOS/Linux
+./emsdk install 4.0.21
+./emsdk activate 4.0.21
+source ./emsdk_env.sh
+```
+
+
+
+## Create your project
+
+Use the CLI-managed workflow with `spacetime build`, which wraps CMake + `emcc` for you, starts the local server, builds/publishes your module, and generates client bindings.
+
+```bash
+spacetime dev --template basic-cpp
+```
+
+
+Need manual control? You can still drive CMake+emcc directly (see `spacetimedb/CMakeLists.txt`), but the recommended path is `spacetime build`/`spacetime dev`.
+
+
+
+
+
+Server code lives in the `spacetimedb` folder; the template uses CMake and the SpacetimeDB C++ SDK.
+
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your C++ module
+│ ├── CMakeLists.txt
+│ └── src/
+│ └── lib.cpp # Server-side logic
+├── Cargo.toml
+└── src/
+ └── main.rs # Rust client application
+```
+
+
+
+## Understand tables and reducers
+
+The template includes a `Person` table and two reducers: `add` to insert, `say_hello` to iterate and log.
+
+```cpp
+#include "spacetimedb.h"
+using namespace SpacetimeDB;
+
+struct Person { std::string name; };
+SPACETIMEDB_STRUCT(Person, name)
+SPACETIMEDB_TABLE(Person, person, Public)
+
+SPACETIMEDB_REDUCER(add, ReducerContext ctx, std::string name) {
+ ctx.db[person].insert(Person{name});
+ return Ok();
+}
+
+SPACETIMEDB_REDUCER(say_hello, ReducerContext ctx) {
+ for (const auto& person : ctx.db[person]) {
+ LOG_INFO("Hello, " + person.name + "!");
+ }
+ LOG_INFO("Hello, World!");
+ return Ok();
+}
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then call reducers and inspect data right from the CLI.
+
+```bash
+cd my-spacetime-app
+
+# Insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+
+# Call say_hello to greet everyone
+spacetime call say_hello
+
+# View the module logs
+spacetime logs
+```
+
+## Notes
+
+- To use a local SDK clone instead of the fetched archive, set `SPACETIMEDB_CPP_SDK_DIR` before running `spacetime dev`/`spacetime build`.
+- The template builds to WebAssembly with exceptions disabled (`-fno-exceptions`).
+- If `emcc` is not found, re-run the appropriate `emsdk_env` script to populate environment variables.
diff --git a/templates/basic-cs/.template.json b/templates/basic-cs/.template.json
index b85112b2e07..3acf693d379 100644
--- a/templates/basic-cs/.template.json
+++ b/templates/basic-cs/.template.json
@@ -1,5 +1,9 @@
{
"description": "A basic C# client and server template with only stubs for code",
"client_lang": "csharp",
- "server_lang": "csharp"
+ "server_lang": "csharp",
+ "builtWith": [
+ "SpacetimeDB.ClientSDK",
+ "SpacetimeDB.Runtime"
+ ]
}
diff --git a/templates/basic-cs/README.md b/templates/basic-cs/README.md
new file mode 100644
index 00000000000..d693ce55ad2
--- /dev/null
+++ b/templates/basic-cs/README.md
@@ -0,0 +1,117 @@
+Get a SpacetimeDB C# app running in under 5 minutes.
+
+## Prerequisites
+
+- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Install .NET WASI workload
+
+SpacetimeDB C# modules compile to WebAssembly using the WASI experimental workload.
+
+```bash
+dotnet workload install wasi-experimental
+```
+
+
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a C# SpacetimeDB module.
+
+This will start the local SpacetimeDB server, compile and publish your module, and generate C# client bindings.
+
+```bash
+spacetime dev --template basic-cs
+```
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/Lib.cs` to add tables and reducers. Use the generated bindings in the client project.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ ├── StdbModule.csproj
+│ └── Lib.cs # Server-side logic
+├── client.csproj
+├── Program.cs # Client application
+└── module_bindings/ # Auto-generated types
+```
+
+
+
+## Understand tables and reducers
+
+Open `spacetimedb/Lib.cs` to see the module code. The template includes a `Person` table and two reducers: `Add` to insert a person, and `SayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```csharp
+using SpacetimeDB;
+
+public static partial class Module
+{
+ [SpacetimeDB.Table(Accessor = "Person", Public = true)]
+ public partial struct Person
+ {
+ public string Name;
+ }
+
+ [SpacetimeDB.Reducer]
+ public static void Add(ReducerContext ctx, string name)
+ {
+ ctx.Db.Person.Insert(new Person { Name = name });
+ }
+
+ [SpacetimeDB.Reducer]
+ public static void SayHello(ReducerContext ctx)
+ {
+ foreach (var person in ctx.Db.Person.Iter())
+ {
+ Log.Info($"Hello, {person.Name}!");
+ }
+ Log.Info("Hello, World!");
+ }
+}
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM Person"
+ name
+---------
+ "Alice"
+
+# 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, World!
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [C# SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/csharp-reference) for detailed API docs
diff --git a/templates/basic-rs/.template.json b/templates/basic-rs/.template.json
index 85ebfd88dc7..ac616be16e3 100644
--- a/templates/basic-rs/.template.json
+++ b/templates/basic-rs/.template.json
@@ -1,5 +1,10 @@
{
"description": "A basic Rust client and server template with only stubs for code",
"client_lang": "rust",
- "server_lang": "rust"
+ "server_lang": "rust",
+ "builtWith": [
+ "log",
+ "spacetimedb-sdk",
+ "spacetimedb"
+ ]
}
diff --git a/templates/basic-rs/README.md b/templates/basic-rs/README.md
index 968af7be799..083102976ec 100644
--- a/templates/basic-rs/README.md
+++ b/templates/basic-rs/README.md
@@ -1,15 +1,103 @@
-# SpacetimeDB Rust Client
+Get a SpacetimeDB Rust app running in under 5 minutes.
-A basic Rust client for SpacetimeDB.
+## Prerequisites
-## Setup
+- [Rust](https://www.rust-lang.org/tools/install) installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
-1. Build and publish your server module
-2. Generate bindings:
- ```
- spacetime generate --lang rust --out-dir src/module_bindings
- ```
-3. Run the client:
- ```
- cargo run
- ```
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a Rust SpacetimeDB module.
+
+This will start the local SpacetimeDB server, compile and publish your module, and generate Rust client bindings.
+
+```bash
+spacetime dev --template basic-rs
+```
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/lib.rs` to add tables and reducers. Use the generated bindings in `src/module_bindings/` to build your client.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ ├── Cargo.toml
+│ └── src/
+│ └── lib.rs # Server-side logic
+├── Cargo.toml
+├── src/
+│ ├── main.rs # Client application
+│ └── module_bindings/ # Auto-generated types
+└── README.md
+```
+
+
+
+## Understand tables and reducers
+
+Open `spacetimedb/src/lib.rs` 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.
+
+```rust
+use spacetimedb::{ReducerContext, Table};
+
+#[spacetimedb::table(accessor = person, public)]
+pub struct Person {
+ name: String,
+}
+
+#[spacetimedb::reducer]
+pub fn add(ctx: &ReducerContext, name: String) {
+ ctx.db.person().insert(Person { name });
+}
+
+#[spacetimedb::reducer]
+pub fn say_hello(ctx: &ReducerContext) {
+ for person in ctx.db.person().iter() {
+ log::info!("Hello, {}!", person.name);
+ }
+ log::info!("Hello, World!");
+}
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# 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, World!
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [Rust SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/rust-reference) for detailed API docs
diff --git a/templates/basic-ts/.template.json b/templates/basic-ts/.template.json
index f81df6ce52c..5039ff8aac2 100644
--- a/templates/basic-ts/.template.json
+++ b/templates/basic-ts/.template.json
@@ -1,5 +1,10 @@
{
"description": "A basic TypeScript client and server template with only stubs for code",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "esbuild",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/basic-ts/README.md b/templates/basic-ts/README.md
new file mode 100644
index 00000000000..a90b1813f62
--- /dev/null
+++ b/templates/basic-ts/README.md
@@ -0,0 +1,107 @@
+Get a SpacetimeDB TypeScript app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a TypeScript SpacetimeDB module.
+
+This will start the local SpacetimeDB server, publish your module, and generate TypeScript client bindings.
+
+```bash
+spacetime dev --template basic-ts
+```
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Use the generated bindings in `src/module_bindings/` to build your client.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/
+│ ├── main.ts # Client application
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/browser-ts/.template.json b/templates/browser-ts/.template.json
index 8cc8855138b..9cff3099637 100644
--- a/templates/browser-ts/.template.json
+++ b/templates/browser-ts/.template.json
@@ -1,5 +1,10 @@
{
"description": "Browser web app with TypeScript server",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "typescript",
+ "vite",
+ "spacetimedb"
+ ]
}
diff --git a/templates/browser-ts/README.md b/templates/browser-ts/README.md
new file mode 100644
index 00000000000..7e69847d072
--- /dev/null
+++ b/templates/browser-ts/README.md
@@ -0,0 +1,106 @@
+Get a SpacetimeDB app running in the browser with inline JavaScript.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a TypeScript SpacetimeDB module.
+
+This will start the local SpacetimeDB server, publish your module, and generate TypeScript client bindings.
+
+```bash
+spacetime dev --template browser-ts
+```
+
+
+
+## Build the client bindings
+
+The generated TypeScript bindings need to be bundled into a JavaScript file that can be loaded in the browser via a script tag.
+
+```bash
+cd my-spacetime-app
+npm install
+npm run build
+```
+
+
+
+## Open in browser
+
+Open `index.html` directly in your browser. The app connects to SpacetimeDB and displays data in real-time.
+
+The JavaScript code runs inline in a script tag, using the bundled `DbConnection` class.
+
+:::tip
+The browser IIFE bundle also exposes the generated `tables` query builders, so you can use query-builder subscriptions here too.
+:::
+
+```html
+
+
+
+
+```
+
+
+
+## Call reducers
+
+Reducers are functions that modify data — they're the only way to write to the database.
+
+```javascript
+// Call a reducer with named arguments
+conn.reducers.add({ name: 'Alice' });
+```
+
+
+
+## React to changes
+
+Register callbacks to update your UI when data changes.
+
+```javascript
+conn.db.person.onInsert((ctx, person) => {
+ console.log('New person:', person.name);
+});
+
+conn.db.person.onDelete((ctx, person) => {
+ console.log('Removed:', person.name);
+});
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/bun-ts/.template.json b/templates/bun-ts/.template.json
index 2d523dc53b8..08fdc2fa863 100644
--- a/templates/bun-ts/.template.json
+++ b/templates/bun-ts/.template.json
@@ -2,5 +2,10 @@
"description": "Bun TypeScript client and server template",
"client_framework": "Bun",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "bun",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/bun-ts/README.md b/templates/bun-ts/README.md
new file mode 100644
index 00000000000..21e5e33ef17
--- /dev/null
+++ b/templates/bun-ts/README.md
@@ -0,0 +1,232 @@
+Get a SpacetimeDB Bun app running in under 5 minutes.
+
+## Prerequisites
+
+- [Bun](https://bun.sh/) installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Bun client.
+
+This will start the local SpacetimeDB server, publish your module, and generate TypeScript bindings.
+
+```bash
+spacetime dev --template bun-ts
+```
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/main.ts` to build your Bun client.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/
+│ ├── main.ts # Bun client script
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Run the client
+
+In a new terminal, run the Bun client. It will connect to SpacetimeDB and start an interactive CLI where you can add people and query the database.
+
+```bash
+# Run with auto-reload during development
+bun run dev
+
+# Or run once
+
+bun run start
+
+```
+
+
+
+## Use the interactive CLI
+
+The 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: bun-ts
+
+Connected to SpacetimeDB!
+Identity: abc123def456...
+
+Current people (0):
+(none yet)
+
+Commands:
+ - 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 sayHello reducer (check server logs)
+
+````
+
+
+
+## Understand the client code
+
+Open `src/main.ts` to see the Bun client. It uses `DbConnection.builder()` to connect to SpacetimeDB, subscribes to tables, and sets up the interactive CLI using Bun's native APIs.
+
+Unlike browser apps, Bun stores the authentication token in a file using `Bun.file()` and `Bun.write()`.
+
+```typescript
+import { DbConnection } from './module_bindings/index.js';
+
+// Build and establish connection
+DbConnection.builder()
+ .withUri(HOST)
+ .withDatabaseName(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();
+````
+
+
+
+## Test with the SpacetimeDB CLI
+
+You can also use the SpacetimeDB CLI to call reducers and query your data directly. Changes made via the CLI will appear in your Bun client in real-time.
+
+```bash
+# 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 sayHello 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!
+
+````
+
+
+
+## Bun-specific features
+
+**Native WebSocket:** Bun has built-in WebSocket support, so no additional packages like `undici` are needed.
+
+**Built-in TypeScript:** Bun runs TypeScript directly without transpilation, making startup faster and eliminating the need for `tsx` or `ts-node`.
+
+**Environment variables:** Bun automatically loads `.env` files. Configure the connection using `SPACETIMEDB_HOST` and `SPACETIMEDB_DB_NAME` environment variables.
+
+**File APIs:** The template uses `Bun.file()` and `Bun.write()` for token persistence, which are faster than Node.js `fs` operations.
+
+```bash
+# Configure via environment variables
+SPACETIMEDB_HOST=ws://localhost:3000 \
+SPACETIMEDB_DB_NAME=my-app \
+bun run start
+
+# Or create a .env file (Bun loads it automatically)
+echo "SPACETIMEDB_HOST=ws://localhost:3000" > .env
+echo "SPACETIMEDB_DB_NAME=my-app" >> .env
+bun run start
+````
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/chat-console-cs/.template.json b/templates/chat-console-cs/.template.json
index 0a476ac93f0..e73f0e97f61 100644
--- a/templates/chat-console-cs/.template.json
+++ b/templates/chat-console-cs/.template.json
@@ -1,5 +1,8 @@
{
"description": "C# server/client implementing quickstart chat",
"client_lang": "csharp",
- "server_lang": "csharp"
+ "server_lang": "csharp",
+ "builtWith": [
+ "SpacetimeDB.Runtime"
+ ]
}
diff --git a/templates/chat-console-rs/.template.json b/templates/chat-console-rs/.template.json
index 07ad0e5291a..e51990cfd62 100644
--- a/templates/chat-console-rs/.template.json
+++ b/templates/chat-console-rs/.template.json
@@ -1,5 +1,10 @@
{
"description": "Rust server/client implementing quickstart chat",
"client_lang": "rust",
- "server_lang": "rust"
+ "server_lang": "rust",
+ "builtWith": [
+ "log.workspace",
+ "spacetimedb-sdk",
+ "spacetimedb"
+ ]
}
diff --git a/templates/chat-react-ts/.template.json b/templates/chat-react-ts/.template.json
index c4a20fefa4a..6ca582e36b5 100644
--- a/templates/chat-react-ts/.template.json
+++ b/templates/chat-react-ts/.template.json
@@ -1,5 +1,22 @@
{
"description": "TypeScript server/client implementing quickstart chat",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "react",
+ "react-dom",
+ "eslint",
+ "testing-library",
+ "vitejs",
+ "eslint-plugin-react-hooks",
+ "eslint-plugin-react-refresh",
+ "globals",
+ "jsdom",
+ "prettier",
+ "typescript",
+ "typescript-eslint",
+ "vite",
+ "vitest",
+ "spacetimedb"
+ ]
}
diff --git a/templates/deno-ts/.template.json b/templates/deno-ts/.template.json
index 9b815e8c464..0bc1e4b7f36 100644
--- a/templates/deno-ts/.template.json
+++ b/templates/deno-ts/.template.json
@@ -1,5 +1,10 @@
{
"description": "Deno TypeScript client and server template",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "deno",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/deno-ts/README.md b/templates/deno-ts/README.md
new file mode 100644
index 00000000000..3b72e75af58
--- /dev/null
+++ b/templates/deno-ts/README.md
@@ -0,0 +1,245 @@
+Get a SpacetimeDB Deno app running in under 5 minutes.
+
+## Prerequisites
+
+- [Deno](https://deno.land/) installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+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.
+
+```bash
+spacetime dev --template deno-ts
+```
+
+
+
+## Explore the project structure
+
+Your 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)
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Run the client
+
+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.
+
+```bash
+# Run with auto-reload during development
+pnpm run dev
+# or: npm run dev
+
+# Or run once
+pnpm run start
+# or: npm run start
+```
+
+
+
+## Use the interactive CLI
+
+The 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:
+ - 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 sayHello reducer (check server logs)
+
+````
+
+
+
+## Understand the client code
+
+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()`.
+
+```typescript
+import { DbConnection } from './module_bindings/index.ts';
+
+// Build and establish connection
+DbConnection.builder()
+ .withUri(HOST)
+ .withDatabaseName(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();
+````
+
+
+
+## Test with the SpacetimeDB CLI
+
+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.
+
+```bash
+# 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 sayHello 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!
+
+````
+
+
+
+## Deno-specific features
+
+**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.
+
+```bash
+# 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](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/nextjs-ts/.template.json b/templates/nextjs-ts/.template.json
index 85589e54e1c..ad1d03c3b99 100644
--- a/templates/nextjs-ts/.template.json
+++ b/templates/nextjs-ts/.template.json
@@ -2,5 +2,12 @@
"description": "Next.js App Router with TypeScript server",
"client_framework": "Next.js",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "next",
+ "react",
+ "react-dom",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/nextjs-ts/README.md b/templates/nextjs-ts/README.md
new file mode 100644
index 00000000000..9fc4e60cca9
--- /dev/null
+++ b/templates/nextjs-ts/README.md
@@ -0,0 +1,195 @@
+Get a SpacetimeDB Next.js app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Next.js client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Next.js development server.
+
+```bash
+spacetime dev --template nextjs-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:3000](http://localhost:3000) to see your app running.
+
+The `spacetime dev` command automatically configures your app to connect to SpacetimeDB via environment variables in `.env.local`.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code using the Next.js App Router.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `app/page.tsx` and `app/PersonList.tsx` to build your UI.
+
+```
+my-nextjs-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # SpacetimeDB module logic
+├── app/ # Next.js App Router
+│ ├── layout.tsx # Root layout with providers
+│ ├── page.tsx # Server Component (fetches initial data)
+│ ├── PersonList.tsx # Client Component (real-time updates)
+│ └── providers.tsx # SpacetimeDB provider for real-time
+├── lib/
+│ └── spacetimedb-server.ts # Server-side data fetching
+├── src/
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+
+
+## Understand server-side rendering
+
+The SpacetimeDB SDK works both server-side and client-side. The template uses a hybrid approach:
+
+- **Server Component** (`page.tsx`): Fetches initial data during SSR for fast page loads
+- **Client Component** (`PersonList.tsx`): Maintains a real-time WebSocket connection for live updates
+
+The `lib/spacetimedb-server.ts` file provides a utility for server-side data fetching.
+
+```tsx
+// lib/spacetimedb-server.ts
+import { DbConnection, tables } from '../src/module_bindings';
+
+export async function fetchPeople() {
+ return new Promise((resolve, reject) => {
+ const connection = DbConnection.builder()
+ .withUri(process.env.SPACETIMEDB_HOST!)
+ .withDatabaseName(process.env.SPACETIMEDB_DB_NAME!)
+ .onConnect(conn => {
+ conn.subscriptionBuilder()
+ .onApplied(() => {
+ const people = Array.from(conn.db.person.iter());
+ conn.disconnect();
+ resolve(people);
+ })
+ .subscribe(tables.person);
+ })
+ .build();
+ });
+}
+```
+
+
+
+## Use React hooks for real-time data
+
+In client components, use `useTable` to subscribe to table data and `useReducer` to call reducers. The Server Component passes initial data as props for instant rendering.
+
+```tsx
+// app/page.tsx (Server Component)
+import { PersonList } from './PersonList';
+import { fetchPeople } from '../lib/spacetimedb-server';
+
+export default async function Home() {
+ const initialPeople = await fetchPeople();
+ return ;
+}
+```
+
+```tsx
+// app/PersonList.tsx (Client Component)
+'use client';
+
+import { tables, reducers } from '../src/module_bindings';
+import { useTable, useReducer } from 'spacetimedb/react';
+
+export function PersonList({ initialPeople }) {
+ // Real-time data from WebSocket subscription
+ const [people, isLoading] = useTable(tables.person);
+ const addPerson = useReducer(reducers.add);
+
+ // Use server data until client is connected
+ const displayPeople = isLoading ? initialPeople : people;
+
+ return (
+
+ {displayPeople.map((person, i) => - {person.name}
)}
+
+ );
+}
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/nodejs-ts/.template.json b/templates/nodejs-ts/.template.json
index bb21899d82f..ea32f10847b 100644
--- a/templates/nodejs-ts/.template.json
+++ b/templates/nodejs-ts/.template.json
@@ -2,5 +2,12 @@
"description": "Node.js TypeScript client and server template",
"client_framework": "Node.js",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "nodejs",
+ "esbuild",
+ "typescript",
+ "undici",
+ "spacetimedb"
+ ]
}
diff --git a/templates/nodejs-ts/README.md b/templates/nodejs-ts/README.md
new file mode 100644
index 00000000000..66a81387d26
--- /dev/null
+++ b/templates/nodejs-ts/README.md
@@ -0,0 +1,199 @@
+Get a SpacetimeDB Node.js app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Node.js client.
+
+This starts the local SpacetimeDB server, publishes your module, generates TypeScript bindings, and runs the Node.js client.
+
+```bash
+spacetime dev --template nodejs-ts
+```
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/main.ts` to build your Node.js client.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/
+│ ├── main.ts # Node.js client script
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Run the client
+
+`spacetime dev` starts both the server and the Node.js client. The client connects to SpacetimeDB, subscribes to tables, and displays people as they are added or removed. Press Ctrl+C to exit.
+
+```bash
+spacetime dev --template nodejs-ts
+```
+
+
+
+## Call reducers from the SpacetimeDB CLI
+
+Use the SpacetimeDB CLI to add people and invoke reducers. Changes appear in your Node.js client in real time.
+
+```bash
+# Add a person
+spacetime call add Alice
+spacetime call add Bob
+
+# Greet everyone (check server logs)
+
+spacetime call say_hello
+
+# Query the database
+
+spacetime sql "SELECT * FROM person"
+
+````
+
+
+
+## Understand the client code
+
+Open `src/main.ts` to see the Node.js client. It uses `DbConnection.builder()` to connect to SpacetimeDB, subscribes to tables, and registers callbacks for insert/delete events. Unlike browser apps, Node.js stores the authentication token in a file instead of localStorage.
+
+```typescript
+import { DbConnection } from './module_bindings/index.js';
+
+DbConnection.builder()
+ .withUri(HOST)
+ .withDatabaseName(DB_NAME)
+ .withToken(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 people
+ const people = [...ctx.db.person.iter()];
+ console.log('Current people:', people.length);
+ })
+ .subscribeToAllTables();
+
+ // Listen for table changes
+ conn.db.person.onInsert((ctx, person) => {
+ console.log(`[Added] ${person.name}`);
+ });
+ })
+ .build();
+````
+
+
+
+## More CLI examples
+
+The SpacetimeDB CLI can call reducers and query your data. Changes appear in your Node.js client in real time.
+
+```bash
+# 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 sayHello 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!
+
+````
+
+
+
+## Node.js considerations
+
+**WebSocket support:** Node.js 22+ has native WebSocket support. For Node.js 18-21, the SDK automatically uses the `undici` package (included in devDependencies).
+
+**Environment variables:** Configure the connection using `SPACETIMEDB_HOST` and `SPACETIMEDB_DB_NAME` environment variables.
+
+**Exiting:** Press Ctrl+C to stop the client.
+
+```bash
+# Configure via environment variables
+SPACETIMEDB_HOST=ws://localhost:3000 \
+SPACETIMEDB_DB_NAME=my-app \
+npm run start
+
+# Or use a .env file with dotenv
+````
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/nuxt-ts/.template.json b/templates/nuxt-ts/.template.json
index ea34667b01e..3eefe3bf2a3 100644
--- a/templates/nuxt-ts/.template.json
+++ b/templates/nuxt-ts/.template.json
@@ -2,5 +2,11 @@
"description": "Nuxt web app with TypeScript server",
"client_framework": "Nuxt",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "nuxt",
+ "vue",
+ "typescript",
+ "spacetimedb"
+ ]
}
diff --git a/templates/nuxt-ts/README.md b/templates/nuxt-ts/README.md
new file mode 100644
index 00000000000..7df666f1010
--- /dev/null
+++ b/templates/nuxt-ts/README.md
@@ -0,0 +1,227 @@
+Get a SpacetimeDB Nuxt app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Nuxt client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Nuxt development server.
+
+```bash
+spacetime dev --template nuxt-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The template includes a basic Nuxt app connected to SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `components/AppContent.vue` to build your UI, and `app.vue` to configure the SpacetimeDB connection.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # SpacetimeDB module logic
+├── app.vue # Root component with provider
+├── components/
+│ └── AppContent.vue # Main UI component
+├── server/
+│ └── api/
+│ └── people.get.ts # Server-side data fetching
+├── module_bindings/ # Auto-generated types
+├── nuxt.config.ts # Nuxt configuration
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+
+
+## Understand server-side rendering
+
+The SpacetimeDB SDK works both server-side and client-side. The template uses a hybrid approach:
+
+- **Server API route** (`server/api/people.get.ts`): Fetches initial data during SSR for fast page loads
+- **Client composables**: Maintain a real-time WebSocket connection for live updates
+
+The server API route connects to SpacetimeDB, subscribes, fetches data, and disconnects.
+
+```typescript
+// server/api/people.get.ts
+import { DbConnection, tables } from '../../module_bindings';
+
+export default defineEventHandler(async () => {
+ return new Promise((resolve, reject) => {
+ DbConnection.builder()
+ .withUri(process.env.SPACETIMEDB_HOST!)
+ .withDatabaseName(process.env.SPACETIMEDB_DB_NAME!)
+ .onConnect((conn) => {
+ conn.subscriptionBuilder()
+ .onApplied(() => {
+ const people = Array.from(conn.db.person.iter());
+ conn.disconnect();
+ resolve(people);
+ })
+ .subscribe(tables.person);
+ })
+ .build();
+ });
+});
+```
+
+
+
+## Set up the SpacetimeDB provider
+
+The root `app.vue` wraps your app in a `SpacetimeDBProvider` that manages the WebSocket connection. The provider is wrapped in `ClientOnly` so it only runs in the browser, while SSR uses the server API route for initial data.
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+## Use composables and SSR data together
+
+Use `useFetch` to load initial data server-side, then Vue composables for real-time updates on the client. The component displays server-fetched data immediately while the WebSocket connection establishes.
+
+```vue
+
+
+```
+
+## Next steps
+
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/react-ts/.template.json b/templates/react-ts/.template.json
index 6dc635a7ccf..e60c63dabc6 100644
--- a/templates/react-ts/.template.json
+++ b/templates/react-ts/.template.json
@@ -2,5 +2,13 @@
"description": "React web app with TypeScript server",
"client_framework": "React",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "react",
+ "react-dom",
+ "vitejs",
+ "typescript",
+ "vite",
+ "spacetimedb"
+ ]
}
diff --git a/templates/react-ts/README.md b/templates/react-ts/README.md
new file mode 100644
index 00000000000..8db4516126e
--- /dev/null
+++ b/templates/react-ts/README.md
@@ -0,0 +1,116 @@
+Get a SpacetimeDB React app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and React client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the React development server.
+
+```bash
+spacetime dev --template react-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The template includes a basic React app connected to SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `client/src/App.tsx` to build your UI.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── client/ # React frontend
+│ └── src/
+│ ├── App.tsx
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/remix-ts/.template.json b/templates/remix-ts/.template.json
index 6a2c68072c3..1259fb05a92 100644
--- a/templates/remix-ts/.template.json
+++ b/templates/remix-ts/.template.json
@@ -2,5 +2,14 @@
"description": "Remix with TypeScript server",
"client_framework": "Remix",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "remix-run",
+ "isbot",
+ "react",
+ "react-dom",
+ "typescript",
+ "vite",
+ "spacetimedb"
+ ]
}
diff --git a/templates/remix-ts/README.md b/templates/remix-ts/README.md
new file mode 100644
index 00000000000..7a5c0504866
--- /dev/null
+++ b/templates/remix-ts/README.md
@@ -0,0 +1,190 @@
+Get a SpacetimeDB Remix app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Remix client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Remix development server.
+
+```bash
+spacetime dev --template remix-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The `spacetime dev` command automatically configures your app to connect to SpacetimeDB via environment variables.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code using Remix with Vite.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `app/routes/_index.tsx` to build your UI.
+
+```
+my-remix-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # SpacetimeDB module logic
+├── app/ # Remix app
+│ ├── root.tsx # Root layout with SpacetimeDB provider
+│ ├── lib/
+│ │ └── spacetimedb.server.ts # Server-side data fetching
+│ └── routes/
+│ └── _index.tsx # Home page with loader
+├── src/
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+
+
+## Understand server-side rendering
+
+The SpacetimeDB SDK works both server-side and client-side. The template uses Remix loaders for SSR:
+
+- **Loader**: Fetches initial data from SpacetimeDB during server rendering
+- **Client**: Maintains a real-time WebSocket connection for live updates
+
+The `app/lib/spacetimedb.server.ts` file provides a utility for server-side data fetching.
+
+```tsx
+// app/lib/spacetimedb.server.ts
+import { DbConnection, tables } from '../../src/module_bindings';
+
+export async function fetchPeople() {
+ return new Promise((resolve, reject) => {
+ const connection = DbConnection.builder()
+ .withUri(process.env.SPACETIMEDB_HOST!)
+ .withDatabaseName(process.env.SPACETIMEDB_DB_NAME!)
+ .onConnect(conn => {
+ conn.subscriptionBuilder()
+ .onApplied(() => {
+ const people = Array.from(conn.db.person.iter());
+ conn.disconnect();
+ resolve(people);
+ })
+ .subscribe(tables.person);
+ })
+ .build();
+ });
+}
+```
+
+
+
+## Use loaders and hooks for data
+
+Use Remix loaders to fetch initial data server-side, then React hooks for real-time updates. The loader data is passed to the component and displayed immediately while the client connects.
+
+```tsx
+// app/routes/_index.tsx
+import { useLoaderData } from '@remix-run/react';
+import { tables, reducers } from '../../src/module_bindings';
+import { useTable, useReducer } from 'spacetimedb/react';
+import { fetchPeople } from '../lib/spacetimedb.server';
+
+export async function loader() {
+ const people = await fetchPeople();
+ return { initialPeople: people };
+}
+
+export default function Index() {
+ const { initialPeople } = useLoaderData();
+
+ // Real-time data from WebSocket subscription
+ const [people, isLoading] = useTable(tables.person);
+ const addPerson = useReducer(reducers.add);
+
+ // Use server data until client is connected
+ const displayPeople = isLoading ? initialPeople : people;
+
+ return (
+
+ {displayPeople.map((person, i) => - {person.name}
)}
+
+ );
+}
+```
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/svelte-ts/.template.json b/templates/svelte-ts/.template.json
index 31bbd725c6a..e6db7ed45e2 100644
--- a/templates/svelte-ts/.template.json
+++ b/templates/svelte-ts/.template.json
@@ -2,5 +2,13 @@
"description": "Svelte web app with TypeScript server",
"client_framework": "Svelte",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "sveltejs",
+ "svelte",
+ "svelte-check",
+ "typescript",
+ "vite",
+ "spacetimedb"
+ ]
}
diff --git a/templates/svelte-ts/README.md b/templates/svelte-ts/README.md
new file mode 100644
index 00000000000..3ef596dd66e
--- /dev/null
+++ b/templates/svelte-ts/README.md
@@ -0,0 +1,114 @@
+Get a SpacetimeDB Svelte app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Svelte client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Svelte development server.
+
+```bash
+spacetime dev --template svelte-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The template includes a basic Svelte app connected to SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/App.svelte` to build your UI.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/ # Svelte frontend
+│ ├── App.svelte
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+## Next steps
+
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/tanstack-ts/.template.json b/templates/tanstack-ts/.template.json
index 76ab7261836..2c7333fa606 100644
--- a/templates/tanstack-ts/.template.json
+++ b/templates/tanstack-ts/.template.json
@@ -2,5 +2,15 @@
"description": "TanStack Start (React + TanStack Query/Router) with TypeScript server",
"client_framework": "TanStack",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "tanstack",
+ "react",
+ "react-dom",
+ "vitejs",
+ "typescript",
+ "vite",
+ "vite-tsconfig-paths",
+ "spacetimedb"
+ ]
}
diff --git a/templates/tanstack-ts/README.md b/templates/tanstack-ts/README.md
new file mode 100644
index 00000000000..090e5bf244e
--- /dev/null
+++ b/templates/tanstack-ts/README.md
@@ -0,0 +1,144 @@
+Get a SpacetimeDB app with TanStack Start running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and TanStack Start.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the development server.
+
+```bash
+spacetime dev --template tanstack-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The template includes a TanStack Start app with TanStack Query integration with SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/routes/index.tsx` to build your UI.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/ # TanStack Start frontend
+│ ├── router.tsx # QueryClient + SpacetimeDB setup
+│ ├── routes/
+│ │ ├── __root.tsx # Root layout
+│ │ └── index.tsx # Main app component
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+
+
+## Query and update data
+
+Use `useSpacetimeDBQuery()` to subscribe to tables with TanStack Query — it returns `[data, loading, query]`. SpacetimeDB React hooks also work with TanStack Start.
+
+```typescript
+import { useSpacetimeDBQuery, useReducer } from 'spacetimedb/tanstack';
+import { tables, reducers } from '../module_bindings';
+
+function App() {
+ const [people, loading] = useSpacetimeDBQuery(tables.person);
+ const addPerson = useReducer(reducers.add);
+
+ if (loading) return Loading...
;
+
+ return (
+
+ {people.map((person, i) => (
+ - {person.name}
+ ))}
+
+ );
+}
+````
+
+## Next steps
+
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/templates/vue-ts/.template.json b/templates/vue-ts/.template.json
index e66e510a0b0..73fa04a4814 100644
--- a/templates/vue-ts/.template.json
+++ b/templates/vue-ts/.template.json
@@ -2,5 +2,13 @@
"description": "Vue.js web app with TypeScript server",
"client_framework": "Vue.js",
"client_lang": "typescript",
- "server_lang": "typescript"
+ "server_lang": "typescript",
+ "builtWith": [
+ "vue",
+ "vitejs",
+ "typescript",
+ "vite",
+ "vue-tsc",
+ "spacetimedb"
+ ]
}
diff --git a/templates/vue-ts/README.md b/templates/vue-ts/README.md
new file mode 100644
index 00000000000..95e5b54e398
--- /dev/null
+++ b/templates/vue-ts/README.md
@@ -0,0 +1,114 @@
+Get a SpacetimeDB Vue app running in under 5 minutes.
+
+## Prerequisites
+
+- [Node.js](https://nodejs.org/) 18+ installed
+- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
+
+Install the [SpacetimeDB CLI](https://spacetimedb.com/install) before continuing.
+
+---
+
+## Create your project
+
+Run the `spacetime dev` command to create a new project with a SpacetimeDB module and Vue client.
+
+This will start the local SpacetimeDB server, publish your module, generate TypeScript bindings, and start the Vue development server.
+
+```bash
+spacetime dev --template vue-ts
+```
+
+
+
+## Open your app
+
+Navigate to [http://localhost:5173](http://localhost:5173) to see your app running.
+
+The template includes a basic Vue app connected to SpacetimeDB.
+
+
+
+## Explore the project structure
+
+Your project contains both server and client code.
+
+Edit `spacetimedb/src/index.ts` to add tables and reducers. Edit `src/App.vue` to build your UI.
+
+```
+my-spacetime-app/
+├── spacetimedb/ # Your SpacetimeDB module
+│ └── src/
+│ └── index.ts # Server-side logic
+├── src/ # Vue frontend
+│ ├── App.vue
+│ └── module_bindings/ # Auto-generated types
+└── package.json
+```
+
+
+
+## Understand tables and reducers
+
+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 `sayHello` to greet everyone.
+
+Tables store your data. Reducers are functions that modify data — they're the only way to write to the database.
+
+```typescript
+import { schema, table, t } from 'spacetimedb/server';
+
+const spacetimedb = schema({
+ person: table(
+ { public: true },
+ {
+ name: t.string(),
+ }
+ ),
+});
+export default spacetimedb;
+
+export const add = spacetimedb.reducer(
+ { name: t.string() },
+ (ctx, { name }) => {
+ ctx.db.person.insert({ name });
+ }
+);
+
+export const sayHello = spacetimedb.reducer(ctx => {
+ for (const person of ctx.db.person.iter()) {
+ console.info(`Hello, ${person.name}!`);
+ }
+ console.info('Hello, World!');
+});
+```
+
+
+
+## Test with the CLI
+
+Open a new terminal and navigate to your project directory. Then use the SpacetimeDB CLI to call reducers and query your data directly.
+
+```bash
+cd my-spacetime-app
+
+# Call the add reducer to insert a person
+spacetime call add Alice
+
+# Query the person table
+spacetime sql "SELECT * FROM person"
+ name
+---------
+ "Alice"
+
+# Call sayHello 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, World!
+```
+
+## Next steps
+
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
diff --git a/tools/templates/README.md b/tools/templates/README.md
new file mode 100644
index 00000000000..151bb130dcc
--- /dev/null
+++ b/tools/templates/README.md
@@ -0,0 +1,29 @@
+# Template Tools
+
+Scripts for maintaining template READMEs and metadata in the SpacetimeDB repo. Output is consumed by [spacetimedb.com](https://github.com/clockworklabs/spacetime-web) for the templates page.
+
+## Scripts
+
+- **generate-readmes** – Converts quickstart MDX docs to Markdown and writes `templates//README.md`. Discovers mappings by parsing `--template X` from quickstart files. Templates can override with a `quickstart` field in `.template.json` (must point to a file in the quickstarts dir).
+- **update-jsons** – Updates `builtWith` in each `templates//.template.json` from package.json, Cargo.toml, and .csproj manifests
+- **generate** – Runs both (readmes first, then jsons)
+
+## Usage
+
+From this directory:
+
+```bash
+pnpm install
+pnpm run generate
+```
+
+Or individually:
+
+```bash
+pnpm run generate-readmes
+pnpm run update-jsons
+```
+
+## When to run
+
+Run after changing quickstart docs (`docs/docs/00100-intro/00200-quickstarts/`) or adding/renaming templates. Commit the generated READMEs and updated `.template.json` files.
diff --git a/tools/templates/generate-template-readmes.ts b/tools/templates/generate-template-readmes.ts
new file mode 100644
index 00000000000..9eacb14eef7
--- /dev/null
+++ b/tools/templates/generate-template-readmes.ts
@@ -0,0 +1,245 @@
+/**
+ * Reads SpacetimeDB quickstart MDX docs, converts them to plain Markdown,
+ * and writes README.md into each template folder. These READMEs are consumed
+ * by spacetimedb.com's process-templates to generate the templates page.
+ *
+ * Run from SpacetimeDB repo root. Writes to templates//README.md.
+ *
+ * Usage: pnpm run generate-readmes (from tools/templates/)
+ */
+
+import { readFile, readdir, writeFile } from 'node:fs/promises';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const REPO_ROOT = path.resolve(__dirname, '../..');
+const TEMPLATES_DIR = path.join(REPO_ROOT, 'templates');
+const QUICKSTARTS_DIR = path.join(
+ REPO_ROOT,
+ 'docs/docs/00100-intro/00200-quickstarts'
+);
+const DOCS_ROOT = path.join(REPO_ROOT, 'docs/docs');
+
+const TEMPLATE_FROM_QUICKSTART_RE = /--template\s+(\S+)/;
+
+/** Parse --template X from quickstart content. Returns template slug or null. */
+function parseTemplateFromQuickstart(content: string): string | null {
+ const match = content.match(TEMPLATE_FROM_QUICKSTART_RE);
+ return match ? match[1] : null;
+}
+
+/** Discover template -> quickstart mapping by parsing --template from each quickstart file. */
+async function discoverQuickstartMapping(): Promise