BGS Docs

Architecture

Here is the architecture of the BGS platform. It is just here to provide a look at the environment your game will be running in.

Architecture

Your game engine will be loaded through NPM, and a CDN will be used to load the UI of your game - inside a sandboxed iframe - to be served to the players.

We believe in separation - for the engine to be independent from the UI. That doesn't mean that they can't be in one module, but the engine should be usable and be interactable with regardless of an UI being present or not.

The pieces your game runs in

Four services make up the platform:

How engines are loaded and run

Engines are ordinary npm packages. The game-server installs each registered game version into an isolated games/ folder — either from the npm registry (name@version) or from an npm pack tarball an admin uploaded (stored on S3, installed by URL). Each engine version gets its own install path, so publishing a new version hot-loads it: new games run the new code with no restart, while ongoing games keep their original version forever.

Engines are third-party code, so calls into them are contained:

How the viewer is served

The viewer is a pre-built JS bundle — the platform does not build game source. It's either fetched from a CDN (e.g. jsDelivr serving your npm package) or uploaded by an admin and served from S3. The api wraps it in a small page (handling script/style dependencies and dark mode) that the web app iframes with a restrictive sandbox attribute. All viewer ↔ platform communication goes through the viewer API event bridge — the viewer never talks to the api or game-server directly.

How a move flows

  1. The viewer emits move; the web app forwards it to the game-server.
  2. The game-server loads the game's engine version, calls move(data, move, player) in the worker thread, then toSave, logSlice, scores, currentPlayer… and stores the new JSON state only if toSave returns a state.
  3. Clocks are updated, notifications (and bot auto-play) are scheduled, and the api pushes the update to every connected client over websocket.
  4. Each viewer receives state:updated, fetches the new state/log, and re-renders.