OpenMAIC-React / src /lib /prompts /snippets /whiteboard-reference.md
muthuk1's picture
Convert OpenMAIC from Next.js to React (Vite)
f56a29b verified
## Whiteboard Reference
### Canvas Specifications
**Dimensions**: 1000 Γ— 563 pixels.
**Coordinate system**: `x = 0` at the left edge, `x = 1000` at the right edge. `y = 0` at the top, `y = 563` at the bottom. Every element has `(left, top)` at its top-left corner.
**Safe zone**: keep content within `x ∈ [20, 980]` and `y ∈ [20, 543]` to leave a 20px margin from the canvas edges.
**Reference points**:
- Centered horizontally: `x = (1000 - width) / 2`
- Centered vertically: `y = (563 - height) / 2`
- Two-column layout: left column `x ∈ [20, 480]`, right column `x ∈ [520, 980]` (40px gutter)
### JSON Output Context
Whiteboard actions are `{"type":"action","name":"wb_...", "params":{...}}` items inside the JSON array your response is required to be. All positions are integers (or decimals accepted, but stay in pixel units).
**LaTeX fields deserve special care β€” see the "LaTeX JSON Escape" section below.**
### Action Reference
For every whiteboard action, the JSON shape below is the **complete, canonical** form. All other prose in this file assumes these shapes.
#### wb_open
Open the whiteboard before drawing. Once open, `wb_draw_*` calls auto-render.
```json
{"type":"action","name":"wb_open","params":{}}
```
No parameters. Call before any `wb_draw_*`. Not required before every `wb_draw_*` β€” only once at the start of a drawing phase.
#### wb_draw_text
Place plain text. Use for notes, steps, labels β€” **not** for math formulas (use `wb_draw_latex` instead).
```json
{"type":"action","name":"wb_draw_text","params":{"content":"Step 1: identify forces","x":60,"y":60,"width":600,"height":43,"fontSize":18,"color":"#333333"}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `content` | string | yes | Plain text or HTML `<p>` block. No LaTeX commands. |
| `x` | number | yes | Left edge in pixels. |
| `y` | number | yes | Top edge in pixels. |
| `width` | number | no (default 400) | Text container width. |
| `height` | number | no (default 100) | Text container height. Use the Font Size Table below to pick a matching height. |
| `fontSize` | number | no (default 18) | Point size. Pick from the Font Size Table. |
| `color` | string | no (default `#333333`) | Hex color. |
| `elementId` | string | no | Stable ID for later `wb_delete`. |
**Common mistake**: embedding LaTeX like `"content":"\\frac{a}{b}"` in a text element β€” KaTeX is NOT run on text content, so the raw backslash prints. Use `wb_draw_latex` for any math.
#### wb_draw_shape
Place a geometric shape. Use for annotations, groupings, or simple diagrams.
```json
{"type":"action","name":"wb_draw_shape","params":{"shape":"rectangle","x":60,"y":200,"width":200,"height":100,"fillColor":"#5b9bd5"}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `shape` | `"rectangle"` \| `"circle"` \| `"triangle"` | yes | Primitive shape. |
| `x`, `y` | number | yes | Top-left of the shape's bounding box. |
| `width`, `height` | number | yes | Bounding box size. |
| `fillColor` | string | no (default `#5b9bd5`) | Hex fill color. |
| `elementId` | string | no | Stable ID. |
**Common mistake**: drawing a "parabola" as `wb_draw_shape` with `shape:"triangle"` or as a sequence of `wb_draw_line` segments. Neither renders a curve β€” there is no function-plot primitive. Prefer explaining algebraically or with a table of key points until this gap is closed.
#### wb_draw_line
Draw a straight line or arrow.
```json
{"type":"action","name":"wb_draw_line","params":{"startX":100,"startY":300,"endX":400,"endY":300,"color":"#333333","width":2,"points":["","arrow"]}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `startX`, `startY` | number | yes | Start coordinates. |
| `endX`, `endY` | number | yes | End coordinates. |
| `color` | string | no (default `#333333`) | Hex color. |
| `width` | number | no (default 2) | **Stroke thickness**, NOT line length. Keep 2–4. |
| `style` | `"solid"` \| `"dashed"` | no (default `"solid"`) | Line style. |
| `points` | `[start, end]` of `""` or `"arrow"` | no (default `["",""]`) | Arrow markers at each end. |
| `elementId` | string | no | Stable ID. |
**Common mistake**: setting `width` to the desired span (e.g., 300). `width` is stroke thickness; arrow markers scale with it β€” `width:60` produces a 180Γ—180 arrowhead.
#### wb_draw_latex
Render a math formula via KaTeX.
```json
{"type":"action","name":"wb_draw_latex","params":{"latex":"\\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}","x":100,"y":80,"height":80}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `latex` | string | yes | LaTeX source. **Every `\` must be written as `\\` in the JSON string β€” see "LaTeX JSON Escape" below.** |
| `x`, `y` | number | yes | Top-left. |
| `height` | number | no (default 80) | Preferred rendered height. See the LaTeX Element Height Table below. |
| `width` | number | no (default 400) | Max horizontal space. Auto-computed from height Γ— aspect ratio unless this cap kicks in. |
| `color` | string | no (default `#000000`) | Hex color. |
| `elementId` | string | no | Stable ID. |
**Most common mistake**: single-backslash commands. If your rendered board shows literal words like `ext`, `heta`, `imes`, `rac`, `ightarrow`, that is the bug. Next response: rewrite with `\\text`, `\\theta`, etc.
#### wb_draw_chart
Render a data chart.
```json
{"type":"action","name":"wb_draw_chart","params":{"chartType":"bar","x":100,"y":150,"width":500,"height":300,"data":{"labels":["Q1","Q2","Q3"],"legends":["Sales"],"series":[[100,120,140]]}}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `chartType` | `"bar"` \| `"column"` \| `"line"` \| `"pie"` \| `"ring"` \| `"area"` \| `"radar"` \| `"scatter"` | yes | Chart kind. |
| `x`, `y`, `width`, `height` | number | yes | Bounding box. |
| `data.labels` | string[] | yes | X-axis labels. |
| `data.legends` | string[] | yes | Series names (one per row in `series`). |
| `data.series` | number[][] | yes | One inner array per legend, length matches `labels`. |
| `themeColors` | string[] | no | Palette override. |
| `elementId` | string | no | Stable ID. |
**Common mistake**: placing a chart that extends past `x + width = 1000` or `y + height = 563` β€” charts silently clip at canvas edges.
#### wb_draw_table
Render a simple table.
```json
{"type":"action","name":"wb_draw_table","params":{"x":100,"y":200,"width":500,"height":150,"data":[["Variable","Meaning"],["a","Coefficient of xΒ²"],["b","Coefficient of x"],["c","Constant term"]]}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `x`, `y`, `width`, `height` | number | yes | Bounding box. |
| `data` | string[][] | yes | 2D array. First row is header. All rows same length. |
| `outline` | `{width, style, color}` | no | Border style. |
| `theme` | `{color}` | no | Header color. |
| `elementId` | string | no | Stable ID. |
**Common mistake**: putting LaTeX into table cells (`"data":[["y = \\frac{1}{2}"]]`). Cell text is rendered as plain text; the backslashes stay. Put the formula in a separate `wb_draw_latex` adjacent to the table.
#### wb_draw_code
Draw a code block with syntax highlighting. Includes a ~32px header bar.
```json
{"type":"action","name":"wb_draw_code","params":{"language":"python","code":"def greet(name):\n print(f'Hello, {name}')","x":100,"y":120,"width":500,"height":120,"fileName":"hello.py","elementId":"code1"}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `language` | string | yes | `"python"`, `"javascript"`, `"typescript"`, `"json"`, `"go"`, `"rust"`, `"java"`, `"c"`, `"cpp"`, etc. |
| `code` | string | yes | Source. Use `\n` for newlines. |
| `x`, `y` | number | yes | Top-left. |
| `width` | number | no (default 500) | |
| `height` | number | no (default 300) | Includes ~32px header. Budget β‰ˆ 32 + 22 per line + 16 padding. |
| `fileName` | string | no | Shown in the header bar. |
| `elementId` | string | no | **Recommended** β€” lets you edit the block later with `wb_edit_code`. |
**Common mistake**: underestimating height β€” a 10-line block needs ~270px.
#### wb_edit_code
Modify an existing code block line-by-line. Produces smooth animations β€” prefer this over redrawing.
```json
{"type":"action","name":"wb_edit_code","params":{"elementId":"code1","operation":"insert_after","lineId":"L2","content":" return name.upper()"}}
```
| Field | Type | Required | Description |
|---|---|---|---|
| `elementId` | string | yes | Target code block's ID. |
| `operation` | `"insert_after"` \| `"insert_before"` \| `"delete_lines"` \| `"replace_lines"` | yes | Edit operation. |
| `lineId` | string | for inserts | Reference line ID (e.g., `"L2"`) β€” shown in state. |
| `lineIds` | string[] | for delete/replace | Lines to operate on. |
| `content` | string | for insert/replace | New code. Use `\n` for multiple lines. |
**Common mistake**: guessing line IDs. Read the current whiteboard state β€” every code line has a stable ID like `L1`, `L2`, visible in the state context.
#### wb_delete
Remove one element by ID.
```json
{"type":"action","name":"wb_delete","params":{"elementId":"step1"}}
```
**Common use**: step-by-step reveals (draw step 1 with `elementId:"step1"`, explain, delete, draw step 2).
#### wb_clear
Remove **all** elements from the whiteboard. Use sparingly β€” prefer `wb_delete` when 1-2 removals would do.
```json
{"type":"action","name":"wb_clear","params":{}}
```
#### wb_close
Close the whiteboard to reveal the slide canvas. **Do NOT call at the end of a drawing response** β€” students need time to read. Only close when returning to slide-canvas actions (spotlight/laser).
```json
{"type":"action","name":"wb_close","params":{}}
```
### LaTeX JSON Escape (CRITICAL)
This is the single highest-leverage rule on the whiteboard. Read it before every math-heavy response.
**The rule**: in any JSON string containing LaTeX β€” the `latex` param of `wb_draw_latex`, or a `content` param that happens to contain `\\text{...}` β€” **every backslash must be written as `\\` (two characters)** in your JSON output. When the JSON parser reads `"\text"` it interprets `\t` as an ASCII TAB control character, so by the time KaTeX receives your string it is literally `<TAB>ext{...}` β€” no `\text` command, just garbage.
Characters at risk (first character of the LaTeX command collides with a JSON escape):
| Control | JSON escape | LaTeX commands corrupted |
|---|---|---|
| TAB (`\t`) | `\t` | `\text`, `\theta`, `\times`, `\tau`, `\top`, `\tan` |
| CR (`\r`) | `\r` | `\rightarrow`, `\Rightarrow`, `\rho`, `\right`, `\real` |
| FF (`\f`) | `\f` | `\frac`, `\forall`, `\Phi`, `\phi`, `\flat` |
| BS (`\b`) | `\b` | `\beta`, `\binom`, `\bar`, `\bot` |
| VT (`\v`) | `\v` | `\varphi`, `\vec`, `\vdots`, `\vee`, `\varepsilon` |
| LF (`\n`) | `\n` | `\neq`, `\ni`, `\not`, `\notin` |
**Correctness table** (what you write in JSON β†’ what KaTeX renders):
| LaTeX source | ❌ Wrong in JSON | βœ… Right in JSON |
|---|---|---|
| `\frac{a}{b}` | `"\frac{a}{b}"` | `"\\frac{a}{b}"` |
| `\text{εˆθ§„}` | `"\text{εˆθ§„}"` | `"\\text{εˆθ§„}"` |
| `\theta` | `"\theta"` | `"\\theta"` |
| `\times` | `"\times"` | `"\\times"` |
| `\rightarrow` | `"\rightarrow"` | `"\\rightarrow"` |
| `\Rightarrow` | `"\Rightarrow"` | `"\\Rightarrow"` |
| `\circ` | `"\circ"` | `"\\circ"` |
| `\tau` | `"\tau"` | `"\\tau"` |
| `\forall` | `"\forall"` | `"\\forall"` |
| `\beta` | `"\beta"` | `"\\beta"` |
| `\varphi` | `"\varphi"` | `"\\varphi"` |
| `\sqrt{x}` | `"\sqrt{x}"` | `"\\sqrt{x}"` |
| `a^2 + b^2 = c^2` | `"a^2 + b^2 = c^2"` | `"a^2 + b^2 = c^2"` (no backslash β€” stays the same) |
**Self-check heuristic**: if your previous turn's rendered whiteboard shows literal tokens like `ext`, `heta`, `imes`, `rac`, `irc`, `ightarrow`, `orall`, `eta`, `arphi`, `eq`, you emitted single-backslash LaTeX. In this turn, emit the same formula again with double backslashes, via `wb_delete` + `wb_draw_latex`, or `wb_clear` + redraw.
**Good complete example**:
```json
{"type":"action","name":"wb_draw_latex","params":{"latex":"\\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}","x":100,"y":80,"height":80}}
```
Renders as: the standard quadratic formula. Count the backslashes in the JSON: 4 pairs of `\\`. Each pair is one backslash in the actual LaTeX string, which is what KaTeX needs.
**Bad example** (this is what produces the `ext`-style garbage):
```json
{"type":"action","name":"wb_draw_latex","params":{"latex":"\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}","x":100,"y":80,"height":80}}
```
The JSON parser sees `\f` (form feed), `\p` (kept as `\p`), `\s` (kept as `\s`). KaTeX then receives a broken string where `\frac` is gone. Whether KaTeX complains or silently renders wrong, the board is broken.
### Bounds & Overlap
The canvas is **1000 Γ— 563**. Elements that extend past the edges are clipped.
**Hard bounds** (every element):
- `x β‰₯ 0` and `x + width ≀ 1000`
- `y β‰₯ 0` and `y + height ≀ 563`
**Safe zone** (preferred): `20 ≀ x`, `x + width ≀ 980`, `20 ≀ y`, `y + height ≀ 542`.
**Spacing**:
- Minimum gap between adjacent elements: 20px
- Vertical stacking: `next.y = prev.y + prev.height + 30`
- Side-by-side: `next.x = prev.x + prev.width + 30`
**Two-column layout**:
- Left column: `x ∈ [20, 480]`, width ≀ 460
- Right column: `x ∈ [520, 980]`, width ≀ 460
- Gutter: 40px
**Before placing every element, walk the existing elements** (listed in the "Current State" section of your context). For each existing `(x, y, width, height)`:
- Reject if the new bbox would cover > 30% of its area.
- If space is tight, choose one: `wb_delete` the existing element, shrink the new element, or pick a free region by scanning the canvas quadrants.
**Worked example** β€” adding a formula below an existing chart at (100, 80) size 500Γ—200:
```
chart occupies x=100..600, y=80..280
next safe y = 80 + 200 + 30 = 310
formula at (100, 310, height 80) β†’ occupies y=310..390
check: y + height = 390 ≀ 563 βœ“
check: no overlap with chart (chart ends at y=280, formula starts at y=310) βœ“
```
### Font Size Table
For `wb_draw_text`:
| Content type | `fontSize` |
|---|---|
| Whiteboard title | 28-32 |
| Section heading | 20-24 |
| Body / annotation | 16-18 |
| Caption / fine print | 12-14 |
Keep 2-4px between adjacent hierarchy levels. **Do not use free-form sizes like 8, 11, 48, 64** β€” pick from this table.
For a given `fontSize` and 1-line text, a matching `height` is roughly `ceil(fontSize Γ— 1.5) + 20` (1.5 line-height plus 10px top/bottom padding).
**Pair text and LaTeX by visual weight.** A LaTeX element at `height:80` visually weighs ~28px text; do NOT place 14px captions next to it. Use this table:
| LaTeX `height` | Companion text `fontSize` |
|---|---|
| 50-60 | 16-20 |
| 70-80 | 20-24 |
| 90-110 | 24-28 |
| 120+ | 28-32 |
When a formula and annotation sit on the same board, their visual weights should match. Large formula next to tiny caption looks broken.
### LaTeX Element Height Table
For `wb_draw_latex` β€” use the category that best matches your formula:
| Category | Examples | `height` |
|---|---|---|
| Inline equations | `E=mc^2`, `a+b=c` | 50-80 |
| With fractions | `\\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}` | 60-100 |
| Integrals / limits | `\\int_0^1 f(x)dx`, `\\lim_{x \\to 0}` | 60-100 |
| Summations with limits | `\\sum_{i=1}^{n} i^2` | 80-120 |
| Matrices | `\\begin{pmatrix}a & b \\\\ c & d\\end{pmatrix}` | 100-180 |
| Standalone fractions | `\\frac{a}{b}` | 50-80 |
| Nested fractions | `\\frac{\\frac{a}{b}}{\\frac{c}{d}}` | 80-120 |
Width is auto-computed from `height Γ— aspect_ratio`; `width` acts as a horizontal cap only.
**Multi-step derivations**: give every step the same `height` so they render at matching vertical sizes. Widths will differ β€” that's correct; it reflects each step's horizontal complexity.
### Pre-Output Checklist
Before emitting whiteboard actions, mentally walk through these:
1. **[LaTeX escape]** Every `\` in `latex` params or in any text with math is written as `\\` in the JSON. Scan for single-backslash `\frac`, `\text`, `\theta`, `\times`, `\rightarrow`, `\circ`, `\beta`, `\varphi` β€” none should appear.
2. **[Hard bounds]** For each element: `x β‰₯ 0`, `y β‰₯ 0`, `x + width ≀ 1000`, `y + height ≀ 563`.
3. **[Overlap]** Walk existing elements from the state; new bbox overlaps none by more than 30%. If tight, `wb_delete` first.
4. **[Font consistency]** Every `fontSize` comes from the Font Size Table (28-32 / 20-24 / 16-18 / 12-14). No 8, 11, 48, 64.
5. **[LaTeX height]** Every `wb_draw_latex` `height` matches the formula category (see the LaTeX Height Table).
6. **[Redraw guard]** The element is not already on the whiteboard β€” if the state lists a formula/chart/table matching your intent, reference it instead of redrawing.
7. **[Element type]** Math expressions use `wb_draw_latex`. Plain text uses `wb_draw_text`. Never embed LaTeX commands in text.
8. **[Safe zone]** Where possible, stay within `x ∈ [20, 980]`, `y ∈ [20, 543]`.
9. **[Leave whiteboard open]** Do not call `wb_close` at the end of a drawing turn. Students need to read.
10. **[Visual weight pairing]** Text that sits next to a LaTeX formula uses a `fontSize` matched to the LaTeX `height` per the pairing table above. No tiny 12-14px text next to height-80 formulas.