[!NOTE] Environment dependencies: Drawing on the board requires
@larksuite/whiteboard-cli(Board Node.js CLI tool), andlark-cli(LarkSuite CLI tool). If execution fails, install manually and retry:npm install -g @larksuite/whiteboard-cli@^0.1.0
[!IMPORTANT] Before executing
npm installto install new dependencies, you must obtain user consent!
Workflow
This is a board, not a webpage. A board is an infinite canvas where elements are freely placed; flex layout is an optional enhancement.
Step 1: 路由 & 读取知识
- 判断渲染路径(见路由表):Mermaid 还是 DSL?
- 读对应 scene 指南 — 了解结构特征和布局策略
- 确定布局策略(见下方快速判断)和构建方式
- 读 references/ 核心模块 — 语法、布局、配色、排版、连线
Step 2: 生成完整 DSL(含颜色)
- 按 content.md 规划信息量和分组
- 按 layout.md 选择布局模式和间距
- 按 style.md 上色(用户没指定时用默认经典色板)
- 按 schema.md 语法输出完整 JSON
- 连线参考 connectors.md,排版参考 typography.md
注意:部分图形(鱼骨/飞轮/柱状/折线等)等, 要按 scene 指南的脚本模板写 .js 脚本生成 JSON:
- node xxx.js → 产出 JSON 文件
- 用产出的 JSON 文件进入 Step 3
Step 3: 渲染 & 审查 → 交付
- 渲染前自查(见下方检查清单)
- 渲染 PNG,检查:
· 信息完整?布局合理?配色协调?
· 文字无截断?连线无交叉?
- 有问题 → 按症状表修复 → 重新渲染(最多 2 轮)
- 2 轮后仍有严重问题 → 考虑走 Mermaid 路径兜底
- 没问题 → 交付:
· 用户要求上传飞书 → 见下方”上传飞书画板”章节中的说明
· 用户未指定 → 展示 PNG 图片给用户
Quick layout strategy decision(see layout.md for details):
| Decision condition | Layout strategy | Construction method |
|---|---|---|
| Clear top-down hierarchy (user layer→service layer→data layer) | Flex layering | Write JSON directly |
| Spatial position carries information (geography, topology, angles) | Pure absolute positioning | Write a script to calculate coordinates (node xxx.js) |
| Multiple independent modules interconnected at the same level | Hybrid (island-style) | Write JSON directly + height estimation assistance |
| Uncertain | Default Flex (safest) | Write JSON directly |
The construction method is a hard constraint: When the scene guide requires "script generation", you must first write a script (.js) and use
nodeto execute it to produce the JSON file. Coordinates in absolute positioning scenarios (fishbone diagrams, flywheel diagrams, bar charts, line charts, etc.) require mathematical calculation; writing JSON directly by hand can easily cause node overlap or connector clipping.
Rendering path selection (DSL or Mermaid)
| Diagram type | Path | Reason |
|---|---|---|
| Mind map | Mermaid | Radial structure auto-layout |
| Sequence diagram | Mermaid | Participants + messages auto-arranged |
| Class diagram | Mermaid | Class relationships auto-layout |
| Pie chart | Mermaid | Natively supported by Mermaid |
| Flowchart | Mermaid | Stably generate structure via Mermaid syntax |
| All other types | DSL | Precise control over style and layout |
Routing rules:
- Automatic Mermaid: Mind map, sequence diagram, class diagram, pie chart, flowchart → default to Mermaid
- Explicit Mermaid: User input contains Mermaid syntax → use Mermaid
- DSL path: All other types → first read the core module, then read the corresponding scene guide
Mermaid path: Refer to scenes/mermaid.md to write the .mmd file, skipping the DSL module.
DSL path: Execute according to the 3 steps in Workflow.
Module index
Core references (required reading for the DSL path)
| Module | File | Description |
|---|---|---|
| DSL syntax | references/schema.md |
Node types, properties, size values |
| Content planning | references/content.md |
Information extraction, density decisions, connector prediction |
| Layout system | references/layout.md |
Grid methodology, Flex mapping, spacing rules |
| Typography rules | references/typography.md |
Font size hierarchy, alignment, line spacing |
| Connector system | references/connectors.md |
Topology planning, anchor selection |
| Color system | references/style.md |
Multiple palettes, visual hierarchy |
Scenario guide (choose one by type)
| Diagram type | File | Use case |
|---|---|---|
| Architecture diagram | scenes/architecture.md |
Layered architecture, microservice architecture |
| Organization chart | scenes/organization.md |
Company organization, tree hierarchy |
| Comparison diagram | scenes/comparison.md |
Solution comparison, feature matrix |
| Fishbone diagram | scenes/fishbone.md |
Causal analysis, root cause analysis |
| Bar chart | scenes/bar-chart.md |
Column chart, bar chart |
| Line chart | scenes/line-chart.md |
Line chart, trend chart |
| Treemap | scenes/treemap.md |
Treemap, hierarchical proportion |
| Funnel chart | scenes/funnel.md |
Conversion funnel, sales funnel |
| Pyramid chart | scenes/pyramid.md |
Hierarchical structure, hierarchy of needs |
| Cycle/flywheel diagram | scenes/flywheel.md |
Growth flywheel, closed-loop chain |
| Milestone | scenes/milestone.md |
Timeline, version evolution |
| Mermaid | scenes/mermaid.md |
Mind map, sequence diagram, class diagram, pie chart, flowchart |
CLI commands
Render:
npx -y @larksuite/whiteboard-cli@^0.1.0 -i my-diagram.json -o ./images/my-diagram.png # DSL 路径
npx -y @larksuite/whiteboard-cli@^0.1.0 -i diagram.mmd -o ./images/diagram.png # Mermaid 路径
npx -y @larksuite/whiteboard-cli@^0.1.0 -i skeleton.json -o ./images/step1.png -l coords.json # 两阶段(提取坐标)
Upload to Feishu whiteboard:
Uploading requires Feishu authentication. When encountering authentication or permission errors, read
../lark-shared/SKILL.mdto learn about login and permission handling.
Step 1: Get the whiteboard token
| What the user provided | How to get the token |
|---|---|
Whiteboard token (XXX) |
Use directly |
| Document URL or doc_id, the document already has a whiteboard | lark-cli docs +fetch --doc <URL> --as user, from the returned <whiteboard token=”XXX”/> extract the token |
| Document URL or doc_id, a new whiteboard needs to be created | lark-cli docs +update --doc <doc_id> --mode append --markdown '<whiteboard type=”blank”></whiteboard>' --as user, from the response's data.board_tokens[0] get the token |
For more operations such as creating and reading Feishu documents, please refer to the lark-doc skill ../lark-doc/SKILL.md。
Step 2: Upload
[!CAUTION] MANDATORY PRE-FLIGHT CHECK (mandatory interception check before upload) When you are about to write content to anexisting whiteboard token ,it is absolutely forbiddento directly execute the upload command! You must strictly follow these two steps: Enforce a Dry Run (status probe) You must first add the
--overwrite --dry-runparameter to the command to probe the current state of the whiteboard. Example command:npx -y @larksuite/whiteboard-cli@^0.1.0 --to openapi -i <输入文件> --format json | lark-cli docs +whiteboard-update --whiteboard-token <Token> --overwrite --dry-run --as userParse the result and intercept
- Carefully read the Dry Run output log.
- If the log contains
XX whiteboard nodes will be deleted: this indicates the whiteboard isnon-empty, and the current operation will overwrite and destroy the user's original diagram!- You must stop the operation immediately, and via the
AskUserQuestiontool (or by replying directly) confirm with the user: "The target whiteboard is currently non-empty. Continuing the update will clear the original XX nodes. Are you sure you want to overwrite?"- Only after the user explicitly authorizes "agree to overwrite" can you remove the
--dry-runActually perform the upload.- The user may ask you not to overwrite and update the canvas content; in that case, remove
--overwriteand--dry-runparameters before uploading.
npx -y @larksuite/whiteboard-cli@^0.1.0 --to openapi -i <输入文件> --format json | lark-cli docs +whiteboard-update --whiteboard-token <画板Token> --yes --as user
Once a canvas is uploaded, it cannot be modified. To upload using an app identity, replace
--as userwith--as bot. If the canvas is not empty, first add--overwrite --dry-runto check the number of nodes to be deleted, confirm with the user, then remove--dry-runand execute.
Symptom→Fix table(refer to this when visual review finds issues):
| Problem seen | What to change |
|---|---|
| Text is truncated | Change height to fit-content |
| Text overflows the right side of the container | Increase width, or shorten the text |
| Nodes overlap and stick together | Increase gap |
| Nodes are crammed together | Increase padding and gap |
| Connector passes through nodes | Adjust fromAnchor/toAnchor or increase spacing |
| Large blank areas | Reduce the outer frame width |
| Text and background colors are too close | Adjust fillColor or textColor |
| The overall layout leans left/right | Adjust the x coordinate of absolute positioning to center the content |
Self-check before rendering
After generating the DSL and before rendering, quickly check:
- Do different groups use different colors? Are nodes in the same group completely consistent in style?
- Outer light-colored background, inner white nodes? (heavy outside, light inside)
- Do all nodes have borders (borderWidth=2)? Is the text clearly readable on the background?
- Do connectors use gray (#BBBFC4), not color?
- Do all frames have the layout attribute set? Are gap and padding explicitly set?
- Do nodes containing text use fit-content for height? Are connectors in the top-level nodes array?
Key constraints quick reference
The most frequently error-prone rules, which must be followed even if you do not read the submodule files.
- The height of nodes containing text must use
'fit-content'— hardcoding a numeric value will truncate the text fill-containerOnly takes effect in a flex parent container —layout: 'none'Under this, width degenerates to 0- connector must be placed in the top-level nodes array — it cannot be nested inside frame children
- Layer order — array order = drawing order. Elements defined later have a higher layer and will cover those defined earlier. Overlapping/floating/annotation elements must be placed at the end of the array.
- x/y inside a flex container are completely ignored — when free positioning is needed, use
layout: 'none'or place it in the top-level nodes
❌ Fatal error: setting x/y inside a flex container does not take effect; nodes are arranged in order
{ "type": "frame", "layout": "vertical", "children": [
{ "type": "rect", "x": 100, "y": 0, "text": "成都" },
{ "type": "rect", "x": 540, "y": 0, "text": "康定" }
]}
✅ Correct: use layout: "none" or place it in the top-level nodes and position it with x/y.