Documentation

Start

v2 · Stable

How a game works

The split with the client

/src/game.ts decides what is legal and what happens. /src/frontend.tsx decides what the player sees. The client never re-implements a rule: it calls useAvailableActions() and useButtons(), which run your functions on the current state.

If you find yourself writing "is this move allowed" in the client, it belongs here instead.

The component contract

import { useMatch, useGameState, useAvailableActions } from "boardweaver/react";

export default function App() {
  const match = useMatch();
  const game = useGameState();
  const available = useAvailableActions();

  return (
    <div>
      {game.spaces("plot").map((space) => (
        <button
          key={space.spaceId}
          onClick={() => match.click({ type: "Click", spaceId: space.spaceId })}
        >
          {space.spaceId}
        </button>
      ))}
    </div>
  );
}

Hard requirements:

  • A default export. No default export is a build error, caught at commit time.
  • No props. The platform mounts your component; nothing passes it anything.
  • Never mount anything yourself. The runtime owns the React root. Do not import react-dom, do not call createRoot.
  • Do not import react for rendering primitives you don't need. react is available for hooks and types, but React itself is provided by the platform and version-locked : your bundle must not ship its own copy.

Need a hand with this?

Join our Discord