Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ pub struct Player {
}
```

</TabItem>
<TabItem value="cpp" label="C++">

```cpp
struct Player {
uint64_t id;
std::string name;
uint32_t age;
Identity user;
};
SPACETIMEDB_STRUCT(Player, id, name, age, user)
SPACETIMEDB_TABLE(Player, players, Public)
FIELD_PrimaryKey(players, id)
```

</TabItem>

</Tabs>
Expand Down Expand Up @@ -147,6 +162,28 @@ fn main() {
}
```

</TabItem>
<TabItem value="cpp" label="C++">

A reducer can be written in C++ like so:

```cpp
SPACETIMEDB_REDUCER(set_player_name, ReducerContext ctx, uint64_t id, std::string name) {
// ...
return Ok();
}
```

And an Unreal C++ [client](#client) can call that reducer:

```cpp
void AMyGameManager::UpdatePlayerName()
{
// ...setup code, then...
Conn->Reducers->SetPlayerName(57, "Marceline");
}
```

</TabItem>
</Tabs>

Expand Down Expand Up @@ -242,6 +279,27 @@ While SpacetimeDB doesn't support nested transactions,
a reducer can [schedule another reducer](https://docs.rs/spacetimedb/latest/spacetimedb/attr.reducer.html#scheduled-reducers) to run at an interval,
or at a specific time.

</TabItem>
<TabItem value="cpp" label="C++">

```cpp
SPACETIMEDB_REDUCER(world, ReducerContext ctx) {
clear_all_tables(ctx);
return Ok();
}

SPACETIMEDB_REDUCER(hello, ReducerContext ctx) {
if (world(ctx).is_err()) {
other_changes(ctx);
}
return Ok();
}
```

While SpacetimeDB doesn't support nested transactions,
a reducer can [schedule another reducer](/tables/schedule-tables) to run at an interval,
or at a specific time.

</TabItem>
</Tabs>

Expand Down Expand Up @@ -361,7 +419,21 @@ fn main() {
```

</TabItem>
<TabItem value="cpp" label="Unreal C++">
<TabItem value="cpp" label="C++">

A procedure can be defined in a C++ module:

```cpp
SPACETIMEDB_PROCEDURE(std::string, make_request, ProcedureContext ctx) {
// ...
return std::string{"result"};
}
```

Use the other tabs (TypeScript/C#/Rust/Unreal C++/Blueprint) for client call examples.

</TabItem>
<TabItem value="cpp-unreal" label="Unreal C++">

An Unreal C++ [client](#client) can call a procedure defined by a Rust or TypeScript module:

Expand Down Expand Up @@ -455,6 +527,17 @@ fn my_player(ctx: &spacetimedb::ViewContext) -> Option<Player> {
}
```

</TabItem>
<TabItem value="cpp" label="C++">

A view can be written in C++ like so:

```cpp
SPACETIMEDB_VIEW(std::optional<Player>, my_player, Public, ViewContext ctx) {
return ctx.db[player_identity].find(ctx.sender);
}
```

</TabItem>
</Tabs>

Expand Down
130 changes: 130 additions & 0 deletions docs/docs/00100-intro/00200-quickstarts/00700-cpp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: C++ Quickstart
sidebar_label: C++
slug: /quickstarts/cpp
hide_table_of_contents: true
---

import { InstallCardLink } from "@site/src/components/InstallCardLink";
import { StepByStep, Step, StepText, StepCode } from "@site/src/components/Steps";

Get a SpacetimeDB C++ app running in under 5 minutes.

## Prerequisites

- [SpacetimeDB CLI](https://spacetimedb.com/install) installed
- Emscripten SDK installed and on PATH (download from [emscripten.org/docs/getting_started/downloads.html](https://emscripten.org/docs/getting_started/downloads.html); use `emsdk_env.bat`/`emsdk_env.sh`)
- CMake 3.20+ and a make/ninja backend
- C++20 toolchain (host) — build targets WASM via Emscripten

<InstallCardLink />

---

<StepByStep>
<Step title="Install Emscripten">
<StepText>
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+.
</StepText>
<StepCode>
```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
```
</StepCode>
</Step>

<Step title="Create your project">
<StepText>
Prefer the CLI-managed build with `spacetime build` (wraps CMake+emcc for you). The basic C++ template starts the local server, builds/publishes your module, and generates client bindings.
</StepText>
<StepCode>
```bash
spacetime dev --template basic-cpp my-spacetime-app
```
</StepCode>
<StepText>
Need manual control? You can still drive CMake+emcc directly (see `spacetimedb/CMakeLists.txt`), but the recommended path is `spacetime build`/`spacetime dev`.
</StepText>
</Step>

<Step title="Explore the project structure">
<StepText>
Server code lives in the `spacetimedb` folder; the template uses CMake and the SpacetimeDB C++ SDK.
</StepText>
<StepCode>
```
my-spacetime-app/
├── spacetimedb/ # Your C++ module
│ ├── CMakeLists.txt
│ └── src/
│ └── lib.cpp # Server-side logic
└── client/ # Client bindings (generated by spacetime dev)
```
</StepCode>
</Step>

<Step title="Understand tables and reducers">
<StepText>
The template includes a `Person` table and two reducers: `add` to insert, `say_hello` to iterate and log.
</StepText>
<StepCode>
```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();
}
```
</StepCode>
</Step>

<Step title="Test with the CLI">
<StepText>
Call reducers and inspect data right from the CLI.
</StepText>
<StepCode>
```bash
# Insert a person
spacetime call <database-name> add Alice

# Query the person table
spacetime sql <database-name> "SELECT * FROM person"

# Greet everyone
spacetime call <database-name> say_hello

# View module logs
spacetime logs <database-name>
```
</StepCode>
</Step>
</StepByStep>

## 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.
11 changes: 9 additions & 2 deletions docs/docs/00200-core-concepts/00100-databases.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ slug: /databases
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

A **module** is a collection of functions and schema definitions, which can be written in TypeScript, C# or Rust. Modules define the structure of your database and the server-side logic that processes and handles client requests.
A **module** is a collection of functions and schema definitions, which can be written in TypeScript, C#, Rust, or C++. Modules define the structure of your database and the server-side logic that processes and handles client requests.

A **database** is a running instance of a module. While a module is the code you write (schema and reducers), a database is the actual deployed entity running on a SpacetimeDB **host** with stored data and active connections.

## Module vs Database

Understanding this distinction is important:

- A **module** is the code you write; it defines your schema (tables) and business logic (reducers, procedures, and views). Modules are compiled and deployed to SpacetimeDB. Rust and C# modules compile to WebAssembly, while TypeScript modules run on V8.
- A **module** is the code you write; it defines your schema (tables) and business logic (reducers, procedures, and views). Modules are compiled and deployed to SpacetimeDB. Rust, C#, and C++ modules compile to WebAssembly, while TypeScript modules run on V8.
- A **database** is a *running instance* of a module; it has the module's schema and logic, plus actual stored data.

You can deploy the same module to multiple databases (e.g. separate environments for testing, staging, production), each with its own independent data. When you update your module code and re-publish, SpacetimeDB will update the database's schema/logic — the existing data remains (though for complicated schema changes you may need to handle migrations carefully).
Expand Down Expand Up @@ -57,6 +57,13 @@ Rust is fully supported for server modules. Rust is a great choice for performan
- The Rust Module SDK docs are [hosted on docs.rs](https://docs.rs/spacetimedb/latest/spacetimedb/).
- [Rust Quickstart Guide](/quickstarts/rust)

</TabItem>
<TabItem value="cpp" label="C++">

C++ is fully supported for server modules. C++ is an excellent choice for developers working with Unreal Engine or those who prefer to stay in the C++ ecosystem.

- [C++ Quickstart Guide](/quickstarts/c-plus-plus)

</TabItem>
</Tabs>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,42 @@ pub fn child_reducer(ctx: &ReducerContext) -> Result<(), String> {
}
```

</TabItem>
<TabItem value="cpp" label="C++">

```cpp
using namespace SpacetimeDB;

// Forward declare child reducer to allow calling it before its definition
ReducerResult child_reducer(ReducerContext&, bool some_condition);

SPACETIMEDB_REDUCER(parent_reducer, ReducerContext ctx, bool some_condition) {
ctx.db[table_a].insert(RowA{ /* ... */ });

// This runs in the SAME transaction
ReducerResult result = child_reducer(ctx, some_condition);
if (result.is_err()) {
return result;
}

ctx.db[table_b].insert(RowB{ /* ... */ });

// All changes from both parent and child commit together
return Ok();
}

SPACETIMEDB_REDUCER(child_reducer, ReducerContext ctx, bool some_condition) {
ctx.db[table_c].insert(RowC{ /* ... */ });

// If this returns Err, the parent's changes also roll back
if (some_condition) {
return Err("Child failed");
}

return Ok();
}
```

</TabItem>
</Tabs>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Choose from several built-in templates:
- `basic-ts` - Basic TypeScript client and server stubs
- `basic-cs` - Basic C# client and server stubs
- `basic-rs` - Basic Rust client and server stubs
- `basic-cpp` - Basic C++ server stubs
- `react-ts` - React web app with TypeScript server
- `chat-console-rs` - Complete Rust chat implementation
- `chat-console-cs` - Complete C# chat implementation
Expand All @@ -81,6 +82,7 @@ Creates a server module only, without any client code. You'll choose your server
- **TypeScript** - Server module in TypeScript
- **Rust** - Server module in Rust
- **C#** - Server module in C#
- **C++** - Server module in C++

The server code will be created in a `spacetimedb/` subdirectory within your project.

Expand Down Expand Up @@ -147,6 +149,18 @@ my-project/
└── README.md
```

</TabItem>
<TabItem value="cpp" label="C++">

```text
my-project/
├── spacetimedb/ # Server module code (C++)
│ ├── CMakeLists.txt
│ └── src/
│ └── lib.cpp
└── README.md
```

</TabItem>
</Tabs>

Expand Down Expand Up @@ -198,6 +212,20 @@ This creates a new Rust project with:
- A `src/lib.rs` with a sample module
- Sample table and reducer definitions

</TabItem>
<TabItem value="cpp" label="C++">

```bash
spacetime init --lang cpp --project-path ./my-project my-project
cd my-project
```

This creates a new C++ project with:

- A `CMakeLists.txt` configured for SpacetimeDB
- A `src/lib.cpp` with a sample module
- Sample table and reducer definitions

</TabItem>
</Tabs>

Expand Down
Loading
Loading