Documentation

Test and maintain

v2 · Stable

Build errors and limits

What is deliberately unavailable

Your frontend runs in a sandboxed frame with no network access, on an opaque origin, under a strict Content Security Policy. These are compile errors, and they would fail at runtime even if they weren't:

  • fetch, XMLHttpRequest, WebSocket, EventSource : the frame cannot talk to any server. All data arrives through the hooks.
  • localStorage, sessionStorage, indexedDB, document.cookie : an opaque origin has no persistent storage.
  • window, document, direct DOM access : use React. For frame size use useViewport(), which is authoritative; there is no window worth measuring.

console and timers (setTimeout, setInterval, requestAnimationFrame) work normally.

This is not a restriction to work around : it is the containment boundary that lets untrusted game code run safely in a player's browser. If you find yourself needing one of these, the answer is almost always that the data belongs in game state, where the server owns it.

Available modules

Only these imports resolve. Bare imports of anything else fail the build.

Module What it is
boardweaver The same runtime the backend uses: GameImage, GameFont, defs, types.
boardweaver/react The match API : every hook in this doc. See react-match-api.
boardweaver/immer Version-locked Immer (produce, produceWithPatches, applyPatches, Patch) for client state. See react-client-state.
boardweaver/dnd Drag and drop primitives.
react, react/jsx-runtime Hooks and types. Provided by the platform.
/src/** Your own tree, by relative or absolute path.

Bundle size

The client bundle is /src/frontend.tsx and all of /src/game.ts, built together into one file that ships to every player on every match load. validate_code rejects it over 1024 KB, measured after minification.

game.ts is in there because the client runs your rules locally to predict the result of a click before the server answers. It is re-exported wholesale, so nothing in it is dropped for going unused by the UI: a large rules engine spends the budget whether or not your frontend touches it. There is currently no way to keep the rules server-only.

The bundle is minified, and comments never survive the build, so neither is worth trimming for size. What counts is executable code. Two things do not count at all:

  • Platform modules. react, boardweaver/react, boardweaver/dnd, boardweaver/immer, boardweaver/ui and boardweaver/motion are runtime externals resolved to the frame, not copies in your bundle.
  • Game images and fonts. Uploaded assets are fetched by URL. Inlining an image as a base64 string literal is the one case where an asset does land in the bundle, and it is the fastest way to blow the limit.

Where code lives

Your source is a tree under /src, entered at /src/game.ts, bundled as a real module graph. Files import each other by relative path (./pieces/Knight) or absolute /src path (/src/pieces/Knight).

Path Holds
/src/game.ts Required entry point. Config + hooks. Small games can live entirely here.
/src/frontend.tsx Required. The React client : see react-frontend.
/src/pieces/ One PieceDef subclass per file, by convention.
/src/spaces/ One SpaceDef subclass per file, by convention.

The only off-tree import the game half may use is "boardweaver". Bare imports of anything else fail the build : there is no node_modules.

Need a hand with this?

Join our Discord