bevy_stdb
A Bevy integration for SpacetimeDB.
Please enjoy this useless AI generated image based on the README contents of this repo.
Overview
bevy_stdb adapts SpacetimeDB's connection and callback model into Bevy-style resources, systems, plugins, and messages. Its built around a few core ideas:
- Configure everything through
StdbPlugin - Expose the active live connection as a Bevy resource via
StdbConnection - Forward SpacetimeDB table callbacks into Bevy
Messages - Store subscription intent independently from the live connection with
StdbSubscriptions - Optionally retry failed connections with
StdbReconnectOptions
The library is organized around connection-scoped lifecycle concerns:
- connection lifecycle: establish the initial connection eagerly or on demand, expose the active connection resource, and track connection state
- table lifecycle: initialize table message channels once and re-bind table callbacks whenever a connection becomes active
- subscription lifecycle: store desired subscription intent and re-apply queued subscriptions when connected
- reconnect lifecycle: optionally retry connection attempts after disconnects using configurable backoff
Features
- Builder-style setup via
StdbPlugin - Connection resource access through
StdbConnection - Table event bridging into normal Bevy
Messages - Managed subscription intent through
StdbSubscriptions - Optional reconnect support through
StdbReconnectOptions
Example
use *;
use *;
use crate;
pub type StdbConn = ;
pub type StdbSubs = ;
Connection driving
bevy_stdb supports two connection-driving modes:
with_background_driver(...): start SpacetimeDB's background processing for the active connectionwith_frame_driver(...): drive SpacetimeDB from the Bevy schedule each frame
Exactly one driver must be configured. These modes are mutually exclusive, and in most applications you'll want with_background_driver(...).
If WASM support is needed, you can enable the browser feature flag in both this crate and your spacetimedb-sdk crate using a target cfg:
# Enable browser support for wasm builds.
# Replace `*` with the versions you are using.
[]
= { = "*", = ["browser"] }
= { = "*", = ["browser"] }
I recommend checking out the bevy_cli 2d template for a good starter example using WASM + native with nice Bevy features configured.
Native background driving
On native targets, the typical choice is run_threaded:
Browser / wasm background driving (async)
On browser targets, use the generated background task helper instead:
If you target both native and browser, I recommend selecting the background driver with cfg:
Bevy frame-tick driving
Use frame_tick when you want Bevy to drive connection progress from Bevy each frame. Internally, bevy_stdb runs this driver from PreUpdate:
use *;
use *;
use crate;
Table registration
Use the StdbPlugin builder methods to register table bindings during app setup.
Each method eagerly registers the Bevy message channels for the row type you specify and stores a deferred binding callback that runs whenever a connection becomes active.
.
.
.
.
This keeps table message registration eager while table callback binding stays lazy and connection-scoped.
Messages
Depending on the table shape, bevy_stdb forwards updates into Bevy messages such as:
InsertMessage<T>DeleteMessage<T>UpdateMessage<T>InsertUpdateMessage<T>
This lets normal Bevy systems react to database changes using message readers.
Subscriptions
StdbSubscriptions stores desired subscription intent separately from the live connection and serves as a lightweight wrapper to manage them.
That means you can:
- declare global (or any other) subscriptions during plugin setup using
with_subscriptions - queue additional subscriptions later from normal Bevy systems
- automatically re-apply queued subscription intent after reconnect
Subscriptions are keyed, so you can refer to them using domain-specific identifiers to do things like resubscribe dynamically or unsubscribe.
There are also messages that are emitted for the on_applied and on_error callbacks for each subscription.
// Check the client cache once a particular subscription has been applied.
Reconnects
Reconnect behavior is opt-in. Use StdbPlugin::with_reconnect with StdbReconnectOptions to enable retry behavior after disconnects. When a reconnect succeeds:
- the
StdbConnectionresource is replaced - table messages are re-bound
- subscriptions are re-applied
Type Aliases
It is useful to define some type aliases of your own. I suggest doing something like this:
pub type StdbConn = ;
pub type StdbSubs = ;
// Or a more constrained version for typical use cases:
// pub type StdbConn<'w> = Res<'w, StdbConnection<DbConnection>>;
// pub type StdbSubs<'w> = ResMut<'w, StdbSubscriptions<SubKeys, RemoteModule>>;
// Usage example
Delayed Connection
Use with_delayed_connection when the initial connection should be requested later at runtime instead of during startup.
use *;
use *;
use crate;
;
Use connect_with_token(...) instead when you want to supply a token at runtime.
Compatibility
| bevy_stdb | bevy | spacetimedb_sdk |
|---|---|---|
| 0.1 - 0.2 | 0.18 | 2.0 |
| 0.3 - 0.5 | 0.18 | 2.1 |
Notes
This crate focuses on table-driven client workflows. Reducer and procedure access still exist through the active StdbConnection, but the primary Bevy-facing event flow is table/message based.
Special thanks to bevy_spacetimedb for the inspiration!