Detailed references

v3 · Preview

Framework v3 is an opt-in preview available to everyone. New games use the stable framework by default.

Design the theme

The theme is /theme.json: the game's colors, light and dark modes, radii, shadows, spacing and page background. The rules pages and the marketing page use it through $ tokens. The client reads it with useGameTheme. Follow these steps in order.

1. Choose the colors

Write every color the game uses in colors, as palettes of shades:

"colors": {
  "neutral": { "50": "#f4f4f2", "800": "#232323" },
  "accent": { "500": "#4d6a7c" }
}

Start each palette and token name with a letter or _, then use letters, digits and _. A hyphen is an error. Name shades with letters, digits and _.

2. Name each color by its job

semanticTokens names what each color is for, with a value for light mode and one for dark mode. A value is a color, or a reference to a shade written palette.shade without $:

"semanticTokens": {
  "text": { "primary": { "light": "neutral.800", "dark": "neutral.50" } },
  "bg": { "surface": { "light": "#ffffff", "dark": "#1b1b1f" } }
}

On the pages, only semantic tokens switch between light and dark. Every other token is fixed. Give every text, background and border color on the pages a semantic token with both modes.

3. Write the whole file

Write /theme.json with write_file. Boardweaver reads the theme only at that path. All fields:

Field Required Holds
version yes 1
fonts yes { "heading", "body", "mono" }, each sans, serif or mono
colors yes palettes of shades
semanticTokens yes groups of { light, dark } tokens
radii yes named lengths, such as { "md": 8 }
shadows yes named shadows: "none" or up to 4 { offsetX, offsetY, blur?, spread?, color, inset? }
palettes yes more named color sets, referenced as palettes.name.key
spacing yes named lengths, such as { "4": 16 }
background no { light, dark }, both required: each { baseColor, layers, border? }, with at most 8 layers
defaultColorMode no light or dark. Without it, the pages follow the visitor's setting.
mood, voice no short words, at most 64 characters, that describe the game's style

A background layer is solid, linear-gradient, radial-gradient, pattern (grid, scanlines, dots, diagonal-lines) or blur-orb. A page without background is white, so with dark semantic tokens also set background.dark.

write_file and patch_file refuse a file that is not JSON (INVALID_THEME_JSON) or does not fit (INVALID_THEME), and say which field is wrong.

4. Use it on the pages

In a page style, a theme value is a $ token:

Token Reads
$semanticTokens.text.primary a semantic token, which follows light and dark
$colors.accent.500 a shade
$palettes.name.key a palette entry
$radii.md, $shadows.card, $spacing.4 a named value

Boardweaver drops a token that does not exist, without an error, so check each token name against /theme.json. Set fontFamily to sans, serif or mono directly.

Run validate_code until it answers no page errors.

5. Use it in the client

useGameTheme() gives the theme as written, with references not resolved. useColorMode() gives "light" or "dark", and changes when the player changes their setting. Resolve a semantic token in the client:

import { useColorMode, useGameTheme, type GameTheme } from "boardweaver/react";

function resolveColor(theme: GameTheme, value: string): string {
  const [palette, shade] = value.split(".");
  return theme.colors[palette]?.[shade] ?? value;
}

export function useToken(group: string, token: string): string | undefined {
  const theme = useGameTheme();
  const mode = useColorMode();
  const pair = theme.semanticTokens[group]?.[token];
  return pair && resolveColor(theme, pair[mode]);
}

Boardweaver paints no background behind the board, so paint it in the client. Use the theme's colors in both modes.

6. Commit

Call commit.

Need a hand with this?

Join our Discord