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'simageSrcis rendered as the piece.- BWSS
Imagenodesrc: GameImageKey: used insiderender()returns. Seestyling.
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
GameImageKeyisstringat the type level : the compiler can't tell you a key is wrong. Typos resolve to "renders nothing."- Per-orientation
width/height(on aPieceOrientation) override thePieceDefclass 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
rendermode : 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>. dis 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 perd; max 16,000 chars total across paths;viewBoxsides ≤ 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.