Write the rules pages
Players read the rules pages in the Rules drawer, in the lobby and during a match, and on the game's public rules link. Follow these steps in order.
1. Plan the pages
/src/rules/index.bwssis the first page. Without it the game has no rules for players: the Rules button is hidden.- Each other page is
/src/rules/<slug>.bwss. Name it with a letter first, then letters, digits,_and-, such assetuporturn-order. - Players reach other pages only through links you write. There is no automatic table of contents.
Done when you have a list of page slugs and each page's purpose, and index links to every other page.
2. Upload the images
Upload each image with upload_art under a key such as BoardOverview: a capital letter first, then letters and digits. Images are JPEG or PNG, at most 5 MB.
Done when every image the pages show has an art key.
3. Write each page
A page is a JSON document: one node, whose children are nodes and plain strings. Write it with write_file. Strings render as plain text, with no markdown.
{
"type": "Box",
"style": { "display": "flex", "flexDirection": "column", "gap": 16, "color": "$semanticTokens.text.primary" },
"children": [
{ "type": "Box", "id": "goal", "style": { "fontSize": 28, "fontWeight": "700" }, "children": ["Goal"] },
{ "type": "Box", "children": ["Be the first to get three marks in a row."] },
{ "type": "Image", "src": "BoardOverview", "alt": "The board at the start" },
{ "type": "Anchor", "href": "setup#board", "style": { "textDecorationLine": "underline" }, "children": ["Setup"] }
]
}
The nodes and styles are below. Colors from the theme are in Design the theme.
Done when each page is written and every rule a new player needs is on a page.
4. Check the pages
Run validate_code. It compiles every page and answers each problem as one line with the file and the path to the node:
/src/rules/index.bwss: children[0].style: Unrecognized key(s) in object: 'border'
write_file does not check a page; only validate_code and commit do. A link to a page that does not exist is not checked: check each link by hand.
Done when validate_code answers no page errors.
5. Commit
Run commit. A failed page compile answers RULES_COMPILE_FAILED with the errors.
Done when commit succeeds.
Nodes
| Node | Props | Renders as |
|---|---|---|
Box |
id?, style?, children? |
a block |
Image |
src (an art key), alt?, style? |
an image. An unknown key fails the compile. |
Svg |
viewBox: { width, height }, paths (1 to 16), style? |
a vector drawing |
Anchor |
href, id?, style?, children? |
a link |
- Every node needs
type. Every other key is checked: an unknown key is an error. - An
idstarts with a letter, then letters, digits,_and-. A link reaches it as#id. hrefis one of#id,slugorslug#id, at most 256 characters. Links to other sites are not allowed.- An
Svgpath is{ d, fill?, stroke?, strokeWidth?, fillRule?, strokeLinecap?, strokeLinejoin?, opacity? }.duses only path commands and numbers, at most 4000 characters. - Every node renders as plain blocks, with no heading or list elements. Make a heading with
fontSizeandfontWeight. Keep line breaks with"whiteSpace": "pre-line".
Styles
A style takes only the properties below. Values are single values: no shorthands such as border or "16px 24px", and no vh, vw, calc or var.
- Values. A length is a number (pixels) or a string in
px,%,emorrem. A color is#hex,rgb(),rgba(), a basic name such aswhite, or a theme token such as$semanticTokens.text.primary.fontWeightis a string:"700". - Layout:
display(flex,block,inline-flex,none),flexDirection,flexWrap,justifyContent,alignItems,gap,flex,flexBasis,flexGrow,flexShrink,width,height,minWidth,maxWidth,minHeight,maxHeight,padding,paddingX,paddingY,paddingTop,paddingRight,paddingBottom,paddingLeft, the same formargin,position(relative,absolute),top,right,bottom,left,overflow. - Text:
fontSize,lineHeight,letterSpacing,fontWeight,fontStyle,fontFamily(sans,serif,mono),textAlign,textTransform,whiteSpace,textOverflow,textDecorationLine,textDecorationStyle,textDecorationColor,textDecorationThickness,textUnderlineOffset,color,textGradient. - Background and border:
backgroundColor,backgroundImage(an art key),backgroundGradient,backgroundSize,backgroundPosition,backgroundRepeat,borderRadius,borderWidth,borderStyle,borderColor, each side'sborderTopWidth(andStyle,Color, forTop,Right,Bottom,Left),boxShadow. - Effects:
opacity,filter,clipPath,transform.
A gradient is a list of layers: { "linear": { "angle": 90, "stops": [{ "color": "#000", "offset": 0 }, { "color": "#fff", "offset": 1 }] } }. A shadow is a list of { offsetX, offsetY, blur?, spread?, color, inset? }. A transform is a list of { rotate }, { translateX }, { translateY } or { scale }.