Have more questions? Join our

Framework v3: rules in Rust

Framework v3 is a preview. A v3 game ships two files:

  • /src/lib.rs: the game's rules, written in Rust against the boardweaver_live SDK (see v3-rust-sdk). Other /src/*.rs files are modules you declare from lib.rs with mod name;.
  • /src/frontend.tsx: the React client. It is exactly a v2 client: the same boardweaver/react hooks (useMatch, useGameState, useAvailableActions, useScores, ...), the same UI and animation libraries, the same no-props default export. See react-match-api.

A game is pinned to v3 when it is created with create_game and frameworkMajor: 3. It starts as tic-tac-toe, and get_example with tic-tac-toe-rust shows the same seed.

How a v3 game is built and run

  • Built with Cargo. validate_code, start_game and commit compile /src/lib.rs to WebAssembly. The SDK owns Cargo.toml: a game uses Rust's standard library, boardweaver_live, serde and serde_json, and nothing else. A compile error comes back as /src/lib.rs:LINE:COL: error[...].
  • Run by the game runner. Each match keeps one live instance of the game's module. Starting a match loads the state once; after that each move sends only the action and gets back what changed. Every move is held to a time and memory budget, and a move that panics fails with the panic's message, leaving the match as it was.
  • Predicted in the browser. The client runs the same module to work out each player's legal actions and scores, and to show a move before the server confirms it. A move that draws randomness (Rng) is never predicted: the browser does not have the server's seed, so it waits for the server. Players cannot learn a roll before the move that makes it.

What a game may and may not do

  • Change state only through Table. Reads are free (table.state()); every change goes through a Table method, which is how the platform learns what changed.
  • Be a pure function of its state. The same state, action and seed must give the same result. Keep nothing in static or global variables: a match can be reloaded from its state at any time, and anything kept outside it is lost.
  • Use Rng for anything random. There is no clock and no other source of randomness.
  • Declare its kinds. kinds() gives each piece and space kind a size, which the client reads as piece.width and space.width.

Not available yet

  • render_game does not run on preview environments.
  • The studio's in-browser preview does not build v3 games; play them through start_game and apply_action, or in a real match.
  • There is no TypeScript type checking of /src/frontend.tsx for v3 games; validate_code checks that it bundles.