Documentation

Rendering and maintenance

v1 · Deprecated

Framework v1 is deprecated for new games. Existing games remain playable and editable.

Images and BWSS nodes

GameImageKey is string. Image keys are dynamic : generated per game from uploaded media, not an enum baked into the framework.

class XToken extends PieceDef {
  readonly kind = "x-token";
  readonly width = 110;
  readonly height = 110;
  readonly orientations = [
    { imageSrc: "XPiece" },                            // GameImageKey string
    { imageSrc: null },                                // blank tile
  ];
}

Where images bind

  • PieceDef.orientations[i].imageSrc: GameImageKey | null : primary use. The current orientation's imageSrc is rendered as the piece.
  • BWSS Image node src: GameImageKey : used inside render() returns. See styling.

Upload flow

upload_art and upload_marketing_image return INVALID_IMAGE for incomplete or unreadable image data. Upload a complete JPEG or PNG file.

Image keys are created when an author uploads media to the game (via the Boardweaver editor's Images panel). Each upload produces a stable string key (e.g. "XPiece", "CardBack"). The author then references that key by string in imageSrc / Image.src.

Authors writing code in this package do not invent image keys : they reference ones the game already has.

null vs missing

imageSrc value Rendered as
null Blank tile (transparent at the piece's width×height).
"ValidKey" The uploaded image.
"UnknownKey" Nothing (renders empty). Never as a URL the author chose : the renderer resolves through the game's images map.

Don't rely on the missing-key fallback to communicate UI state : use null explicitly so intent is clear.

In render mode

A render() function that uses an image uses the Image BWSS node:

readonly render: PieceRenderFn = (piece) => ({
  type: "Image",
  src: "XPiece",
  style: { width: piece.width, height: piece.height },
});

Same key resolution : unknown keys render nothing.

Gotchas

  • GameImageKey is string at the type level : the compiler can't tell you a key is wrong. Typos resolve to "renders nothing."
  • Per-orientation width / height (on a PieceOrientation) override the PieceDef class default for that orientation. Use this when the same piece has multiple sizes per face.
  • A piece can mix image and shape mode across orientations: [{ imageSrc: null }, { imageSrc: "FlippedCard" }] is valid.
  • For dynamic visuals that depend on state (a counter, an animated highlight), use render mode : image keys are static lookups.

Node types

type Allowed inside Notes
"Box" piece renders, space renders Generic container. Children: BWSS nodes or strings (text).
"Image" piece renders, space renders { src: GameImageKey, alt?, style? }. See images.
"Svg" piece renders, space renders { viewBox: {width,height}, paths: [{d, fill?, stroke?, ...}], style? }. Only <svg> + <path> are emitted.
"Pieces" space renders only Insertion-point marker for laid-out piece children. See spaces.

There is no Text node : text is a plain string in a Box's children array.

Box

type PieceBoxNode = { type: "Box"; style?: BwssStyle; children?: (PieceBwssNode | string)[] };
type SpaceBoxNode = { type: "Box"; style?: BwssStyle; children?: (SpaceBwssNode | string)[] };

Same JSON shape; the recursive child union differs: piece-side excludes Pieces.

Image

type ImageNode = { type: "Image"; src: GameImageKey; alt?: string; style?: BwssStyle };

src is resolved through the game's images map at render time. Unknown keys render nothing.

Svg

type SvgNode = {
  type: "Svg";
  viewBox: { width: number; height: number };
  paths: SvgPathChild[];
  style?: BwssStyle;
};
type SvgPathChild = {
  d: string;                                            // SVG path-data string
  fill?: string;
  stroke?: string;
  strokeWidth?: number | string;
  fillRule?: "nonzero" | "evenodd";
  strokeLinecap?: "butt" | "round" | "square";
  strokeLinejoin?: "miter" | "round" | "bevel";
  opacity?: number | string;
};
  • Only <svg> and <path> are emitted. No <g>, <defs>, <linearGradient>, <use>, <foreignObject>, <script>, <text>, <image>.
  • d is a character-class-validated string: digits, command letters (MLHVCSQTAZmlhvcsqtaz), whitespace, +-.eE,. Anything else (incl. <>"'();) is rejected.
  • Caps: max 16 paths per Svg; max 4000 chars per d; max 16,000 chars total across paths; viewBox sides ≤ 10,000.

Pieces

type PiecesNode = { type: "Pieces"; style?: BwssStyle };

Only valid inside a space's render tree. The framework substitutes it with the space's laid-out piece children. style layers over the type-defaulted flex props (Stack / Horizontal / Vertical) : author overrides win.

Need a hand with this?

Join our Discord