Core Specification (based on Excalidraw v0.17+ / latest version of the Obsidian plugin)
File Format Standard
Excalidraw files are in JSON format, with the extension .excalidraw。mustcontain the following top-level fields:
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [],
"appState": {
"gridSize": 20,
"viewBackgroundColor": "#ffffff",
"theme": "light",
"currentItemFontFamily": 1,
"exportBackground": true,
"viewModeEnabled": false
},
"files": {}
}
Warning: If an image is referenced in elements (type: "image"), the corresponding binary data (DataURL) must be provided in the files object; otherwise, opening the file will cause the plugin to crash or load indefinitely.
Rendering Order: In the elements array, index 0 is the bottommost layer, and N is the topmost layer
gridSize: Force align to grid
files: Only used when image embedding is involved; otherwise an empty object
Key Constraints:
- All elements must have a unique id: It is recommended to use nanoid(10) or a random alphanumeric string of 8-12 characters (Excalidraw uses something similar internally); a UUID is unnecessarily long. Duplicates are prohibited.
- All elements must have a seed: A positive integer (recommended 100000 ~ 999999999), used as the random seed to determine hand-drawn jitter and ensure rendering consistency.
- Each element needs version and versionNonce: version starts at 1 and increments (+1 on each modification); versionNonce is a random integer used for sync conflict resolution.
- Coordinate System: Origin (0,0) at the top-left, X to the right, Y downward, unit in pixels.It is strongly recommended to Math.round() all x/y/width/height (except angle), to avoid subpixel blurring.
- Angle Unit: angle usesradians(0 ~ 2π)。
- updated: Unix millisecond timestamp; it is recommended to use the current time (Date.now()) for sorting element modification times. When generating multiple elements, it is recommended to increment (e.g., +1ms) to avoid sync conflicts. Obsidian sync mainly relies on versionNonce and version, not on the monotonicity of updated.
- Rendering Layer (Z-Index): Determined by the
elementsarray order.- Recommended Order: To avoid occlusion, the recommended order is: background containers → foreground containers → arrows → text.
- Binding Relationships: Binding relationships depend only on ID references and are unrelated to array order. Arrow binding depends on the target element's ID already existing.
Common Element Fields (present in most elements; type-specific fields are described later)
Most element objects contain the following fields; some fields are type-specific or optional:
| Field | Type/Value Range | Default Value | Strict Constraint Description |
|---|---|---|---|
id |
string |
- | Globally unique. |
type |
enum |
- | See the type details below. |
x, y |
float |
- | It is recommended to round to integers to prevent anti-aliasing blur. |
width, height |
float |
- | Must be > 0. |
angle |
float |
0 |
Radians (0 ~ 2π). Clockwise rotation. |
strokeColor |
hex |
"#1e1e1e" |
Avoid pure black (#000). |
backgroundColor |
hex |
"transparent" |
Supports 8-digit Hex transparency (e.g. #ff000080)。 |
fillStyle |
enum |
"solid" |
"hachure", "cross-hatch", "solid", "zigzag" |
strokeWidth |
int |
1 |
1 (thin), 2 (standard), 4 (thick). |
strokeStyle |
enum |
"solid" |
"solid", "dashed", "dotted" |
roughness |
int |
1 |
0 (geometric), 1 (hand-drawn), 2 (sketch). |
opacity |
int |
100 |
0-100。 |
groupIds |
string[] |
[] |
Which group it belongs to. Used to group multiple elements together (similar to Ctrl+G), so they are operated on as a whole when moved/deleted.Strict logic: All elements within the same group must have exactly the same group ID string. When generating, it is generally empty, unless it is a composite graphic that needs to be moved in bulk. When copying elements, the group ID must also be copied. |
roundness |
object |
null |
See the detailed object structure below. |
seed |
int |
random |
Positive integer (recommended 100000 ~ 999999999), used to determine the random seed for hand-drawn jitter, ensuring rendering consistency. |
version |
int |
1 |
Incremented automatically on each modification. Defaults to 1 when generating. |
versionNonce |
int |
random |
0 ~ 2^32-1。 |
isDeleted |
bool |
false |
If true, Obsidian will not render this element. |
boundElements |
array |
[] |
Key: Used for two-way binding. |
updated |
int |
time |
Millisecond timestamp. |
link |
string |
null |
Obsidian internal link format. |
locked |
bool |
false |
Whether it is locked. |
frameId |
`string | null` | null |
Important Notes:
- Some fields only apply to specific types (e.g., roundness only applies to rectangle; points/startArrowhead only apply to arrow/line). text elements lack fields such as fillStyle/roughness. Non-applicable fields may be omitted in the JSON.
- When width/height are calculated: width and height must reflect the element's actual rendered bounding box, and should be calculated in real time based on the content when generating (especially for text and arrows); values must not be filled in arbitrarily.
- Text: calculate the actual width and height based on font, font size, and text content
- Arrow: calculate the bounding box from the points array (width = max_x - min_x, height = max_y - min_y)
Example
{
"id": "unique-string",
"type": "...",
"x": 100,
"y": 100,
"width": 120,
"height": 80,
"angle": 0,
"strokeColor": "#1e1e1e",
"backgroundColor": "transparent",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"groupIds": [],
"frameId": null,
"seed": 123456789,
"version": 1,
"versionNonce": 987654321,
"isDeleted": false,
"updated": 1735689600000,
"link": null,
"locked": false
}
Element Type Details and Geometry Logic
Coordinate calculation formula (to avoid subpixel blurriness):
x = Math.round(targetX)y = Math.round(targetY)width = Math.ceil(targetWidth)height = Math.ceil(targetHeight)
Text centering formula (strict version):
textElement.x = container.x + (container.width - textElement.width) / 2;
textElement.y = container.y + (container.height - textElement.height) / 2;
Container types (Rectangle, Ellipse, Diamond)
Corner rounding rules (roundness):
- Right angle:
roundness: null - Legacy proportional corner rounding:
roundness: { "type": 1 }(PROPORTIONAL_RADIUS / LEGACY) - legacy format - Adaptive corner rounding (recommended):
roundness: { "type": 2 }(ADAPTIVE_RADIUS) - current standard recommended value, smoothest, no value needed - Fixed-pixel corner rounding:
roundness: { "type": 3, "value": 20 }(FIXED_RADIUS) - used together with value, provides corner rounding at specific pixels
Note: In versions after 2024, Diamond also supports the roundness object.
1. Rectangle
{
"type": "rectangle",
"roundness": null
}
Corner rounding options:
- Right angle:
roundness: null - Fixed corner rounding:
roundness: { "type": 1, "value": 20 } - Adaptive corner rounding:
roundness: { "type": 2 }
2. Diamond - a separate type (not rectangle + roundness)
{
"type": "diamond",
"roundness": null
}
Diamond corner rounding options:
- Right angle:
roundness: null - Adaptive corner rounding:
roundness: { "type": 2 } - Fixed corner rounding:
roundness: { "type": 3, "value": 10 }
Note: In versions after 2024, Diamond also supports the roundness object.
3. Ellipse
{
"type": "ellipse",
"roundness": null
}
Note: x, y are the top-left corner of the circumscribed rectangle.
4. Text and container binding (mandatory two-way binding)
Extremely high-risk item; text is the part most prone to rendering errors. The following calculations must be strictly followed
{
"type": "text",
"fontSize": 20,
"fontFamily": 1,
"lineHeight": 1.25,
"text": "第一行\n第二行",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "box-1",
"baseline": 18,
"width": 60,
"height": 45
}
Text element description:
fontFamily: 1=Virgil (hand-drawn), 2=Helvetica (sans-serif), 3=Cascadia (code font). Obsidian plugins usually do not support other values.lineHeight: Must be provided, otherwise multi-line text alignment will be messed up.text: Must explicitly include\n, Excalidraw does not automatically wrap text.verticalAlign: "top", "middle", "bottom" (only takes effect when containerId is not null).baseline: Computed value; for multi-line text, it is still the baseline height of the first line.width: The actual width of the text must be precomputed.height: Must include the sum of all line heights.
Binding Rules (Strict):
- The container's boundElements must contain { "type": "text", "id": "text-id" }
- The text's containerId points to the container id
- Text coordinates (centered example): x = container.x + container.width/2 - text.width/2, same for y
- Creation Order: Container first, then text
- Deletion: When container isDeleted: true, the bound text must be deleted at the same time
Important Notes on Text Elements:
- lineHeight: Must be provided, otherwise multi-line text alignment will be messed up. Default value 1.25.
- baseline Dynamism: For multi-line text, baseline is still the baseline height of the first line, not the center of the entire block.
- Alignment Rules:
- verticalAlign ("middle", "top", "bottom") only takes effect when containerId is not null.
- verticalAlign for standalone text is usually ignored and determined by the y coordinate.
- Width and Height Calculation: width and height must accurately reflect the actual rendered size of the text, and height must include the sum of all line heights.
Baseline Calculation Formula (Approximate):
- fontFamily: 1 (Virgil): baseline ≈ fontSize * 0.84
- fontFamily: 2 (Helvetica): baseline ≈ fontSize * 0.76
Warning: Do not rely on hardcoded baseline approximations! In real scenarios (multi-line text, different verticalAlign, varying lineHeight), noticeable offsets will occur.
Strongly Recommended:
- Baseline is the distance from the first line's baseline to the top of the text element.
- Best Practices:
- Use the Excalidraw Automate API's measureText() or getTextSize() to obtain precise width, height, and baseline
- Or in Obsidian, first manually create a text box → export JSON → refer to the actual values
- As a temporary fallback, you can use the range fontSize * 0.78 ~ 0.85 (Virgil), preferring the smaller value (slightly higher is usually more visually acceptable)
- If generating manually, follow these rules:
- Single-line centered: x = container.x + container.width/2 - text.width/2, same for y
5. Arrows and Lines (Arrow / Line)
Arrow coordinates are a relative coordinate system.
{
"type": "arrow",
"x": 100,
"y": 100,
"width": 150,
"height": 50,
"angle": 0,
"points": [
[0, 0],
[150, 0]
],
"lastCommittedPoint": [150, 0],
"startArrowhead": null,
"endArrowhead": "triangle",
"startBinding": {
"elementId": "rect-1",
"focus": 0,
"gap": 8
},
"endBinding": {
"elementId": "rect-2",
"focus": 0,
"gap": 8
},
"strokeSharpness": "round"
}
Notes on Arrow Elements:
type: "arrow" or "line" (straight line, no default arrow style).x,y: The starting point's reference coordinates.width,height: The bounding box calculated from points (must be correct).points:- The starting point is always [0,0], otherwise the arrow will have unpredictable offsets when rendered in Obsidian.
- Subsequent points are relative offsets; absolute coordinates = x+offset value, y+offset value.
- Bend example: [[0,0], [50,50], [150,0]].
lastCommittedPoint: Must equal the last item of points, and always stay consistent with the last element of the points array.startArrowhead: Valid values: "arrow", "triangle", "dot", "bar", "diamond", "circle", "triangle_filled", "arrow_filled", null.endArrowhead: Default value: null (no arrow); commonly used: "triangle" (pointed head), "arrow" (classic arrow).focus: -1 to 1, 0 = most stable at center.gap: Required, recommended 4-12, avoid default spacing being too large.strokeSharpness: "round" (rounded polyline/bezier feel), "sharp" (straight corners).- Other common fields: add as needed.
Description:
- For two-way binding, you must set both the arrow's start/endBinding and the target element's boundElements: [{id: "arrow-id", type: "arrow"}].
- Possible arrowhead values increase as Excalidraw updates (triangle, diamond, etc. added after 2025); null is equivalent to "none".
- strokeSharpness: Controls the style of the arrow's polyline
- "round" → Bezier curve/rounded polyline
- "sharp" → right-angle polyline
- Latest Features: The latest version of Excalidraw supports smart polylines. By properly setting strokeSharpness and the points array, more natural connection effects can be achieved.
Commonly Recommended Combinations:
- Flowchart: startArrowhead: null, endArrowhead: "triangle" or "arrow"
- Double-headed arrow: startArrowhead: "triangle", endArrowhead: "triangle"
- Arrowless connector: set both to null (or use type: "line")
Other Common Element Types
- line: Same structure as arrow, but startArrowhead/endArrowhead default to null.
- frame: type: "frame", additional field "name": "frame title" (displayed at the top of the frame), used to group large areas.
- image: type: "image", requires "fileId": "file ID" (corresponding to a key in the files object), "scale": [1,1].
Strict Requirements: When using an image element, you must provide DataURL data for the corresponding fileId in the top-level files object, in the following format:
"files": { "fileId": { "type": "image/png", "data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" } }
**图片文件说明**:
- `type`:必须准确,与DataURL的mimeType一致。
- `data`:Base64编码的图片数据,格式为data:image/{format};base64,{data}。
**注意**:"type"字段的mimeType必须与DataURL中的mimeType完全一致,否则可能导致图片无法加载。
- **freedraw**:type: "freedraw",points: [[x,y], ...](绝对坐标),用于手绘路径。
**说明**:以上类型覆盖90%架构图/流程图/思维导图场景,其余类型可参考Excalidraw导出JSON。
#### 6. 双向绑定握手协议 (The Binding Handshake)
**核心原则**:在 Excalidraw 中,绑定必须是双向声明的。任何一方缺失都会导致“假绑定”(视觉接触但拖动分离)。
**双向绑定规则**:
- **容器 -> 成员**:容器(Rectangle/Ellipse/Diamond/Frame)的 boundElements 数组内必须包含对象:{"id": "member-id", "type": "text" | "arrow"}。
- **成员 -> 容器**:
- 文本需设置 containerId: "container-id"。
- 箭头需设置 startBinding 或 endBinding。
**严苛警告**:
- 如果容器被 isDeleted: true,但其绑定的文本 isDeleted: false,Obsidian 会渲染一个漂浮在原地的文本。必须级联删除。
- 箭头指向容器时,容器的 boundElements 必须包含箭头的 ID,否则箭头不会跟随容器移动。
##### 场景 A:文本放入矩形 (Text inside Rectangle)
1. **矩形侧**:`boundElements` 必须包含文本 ID。
JSON
"id": "rect-1", "boundElements": [ { "id": "text-1", "type": "text" } ]
2. **文本侧**:`containerId` 必须指向矩形 ID。
JSON
"id": "text-1", "containerId": "rect-1"
3. **坐标对齐**:文本的 `x, y` 必须经过计算,使其位于矩形中心(或指定的 align 位置)。
##### 场景 B:箭头连接矩形 (Arrow connects Rectangles)
1. **箭头侧**:声明 `startBinding` 或 `endBinding`。
JSON
"startBinding": { "elementId": "rect-1", "focus": 0, "gap": 8 }
2. **矩形侧**:`boundElements` 必须包含箭头 ID。
JSON
"boundElements": [ { "id": "text-1", "type": "text" }, { "id": "arrow-1", "type": "arrow" } ]
##### 推荐文件格式
**优先使用 `.excalidraw` 文件格式**,这是纯JSON格式,兼容性最好,不易出错:
- **文件扩展名**:`.excalidraw`
- **文件内容**:纯JSON格式,无任何额外内容
- **格式要求**:严格遵循以下结构
```json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [],
"appState": {},
"files": {}
}
Important Notes:
- Avoid using the
.excalidraw.mdformat, because AI-generated compressed-json structures are prone to errors - Advantages of Pure JSON Format: Simpler, more reliable, less susceptible to interference from editors or IDEs
- Compatibility:
.excalidrawis Excalidraw's native format and has the best compatibility
Generation Specifications:
- The generated file must be in pure JSON format, without any extra content
- Do not include editor markers, line number references, or code block markers in the file
- Ensure the file is encoded as UTF-8 without BOM
- Verify that the generated JSON format is correct; you can use a JSON validation tool to check it
5. Obsidian Deep Integration Specifications
Internal Links
- Format: Supports multiple Obsidian WikiLink formats:
"link": "[[Note]]""link": "[[Note|显示别名]]""link": "[[Note#Heading]]""link": "[[Note#^block-id]]""link": "[[Folder/Note#Section|^alias]]""link": "exec:脚本名"(used to execute Obsidian scripts)
- Behavior: When an element is clicked, Obsidian jumps to the corresponding note or executes the specified script.
- Note: No prefix
file://orobsidian://is needed; write the WikiLink directly. - Limitation: The link field's jump functionality only works in .excalidraw.md files. Links in pure JSON files (.excalidraw) will not be parsed by Obsidian as clickable links.
Obsidian-Specific Metadata
- customData: The Obsidian Excalidraw plugin stores customData in elements. Although it can be omitted during generation, if you want to support certain advanced features (such as specific script triggers), you should be aware of its existence.
"customData": { "someKey": "someValue" } - Internal link format: In addition to the standard WikiLink format, if you want to add functionality like "click a button to execute a script" to an element, the Obsidian plugin supports using exec:script-name in the link field.
Color specification (Excalidraw official palette, #000/#fff prohibited)
- Main text/lines: #1e1e1e (light theme) / #2e2e2e (dark theme)
- Blue: #1971c2 / #a5d8ff
- Red: #e03131 / #ffec99
- Green: #2f9e44 / #b2f2bb
- Gray: #495057 / #e9ecef
- Yellow: #f08c00 / #fff3bf
- Purple: #7048e8 / #e5dbff
Recommendation: In dark themes, prefer using #2e2e2e as strokeColor to improve readability.
Recommended combinations for dark themes:
- strokeColor: "#e0e0e0" or "#d0d0d0" (light gray, improves contrast)
- backgroundColor: "#2d2d2d" or "#1e1e1e" (dark background)
- Text color: "#e0e0e0"
Obsidian integration specification
-
Recommended file format: Diagram.excalidraw (pure JSON)
Advantages:
- Native format, best compatibility
- Pure JSON structure, less prone to errors
- Fast generation and parsing
- Not affected by editors or IDEs
-
Embed syntax
Markdown
![[Diagram.excalidraw]] <!-- 可编辑画布 --> ![[Diagram.excalidraw|600]] <!-- 指定宽度 --> ![[Diagram.excalidraw|600x400]] <!-- 宽高 -->
Important note:
- Avoid using the
.excalidraw.mdformat, because AI-generated compressed-json structures are prone to errors - Prefer pure
.excalidrawfiles for the best compatibility and reliability
Internal links(link field) supports [[Note]], [[Note#heading]], [[Note|alias]], [[Note#^block]]
Common errors and debugging (extended version)
- Duplicate IDs → crash
- Text containerId points to a nonexistent ID or is not declared in boundElements → text misaligned/does not follow
- Text overflow: was text width/height estimated based on the character count? If the text is too long, was
\n? - Arrow points do not start with [0,0] → position offset
- Duplicate or out-of-order updated timestamps → sync loses changes
- Missing seed/version/versionNonce → sync abnormalities
- roundness.type = 3 → invalid (legacy from old versions, deprecated)
- link uses javascript: → XSS risk, prohibited
- Too many floating-point coordinates → integers are recommended to avoid slight misalignment
- Ghost Binding: the arrow declares a binding
rect-1, butrect-1'sboundElementsdoes not contain the arrow ID? (Fix: it must be added bidirectionally). - Non-integer coordinates: did
x: 100.3333333appear? (Fix: except forangle, try to useMath.round()coordinates to improve rendering performance). - Color contrast: was a white line used on a white background? (Fix: ensure
strokeColorhas sufficient contrast).
Best practices
-
Horizontal node spacing 180–250px, vertical 120–180px
-
Fonts: title 28–36px, body 20px, annotations 16px
-
fillStyle: "solid" (recommended), "hachure" (hand-drawn diagonal lines), "cross-hatch"
-
roughness: 1 (standard), 0 (sharp), 2 (extra rough)
-
When generating: containers first → text → arrows (to ensure binding order)
-
Use the current timestamp + an incrementing small offset as updated
Advanced arrow binding techniques
Bidirectional binding is mandatory:
- Arrow: set startBinding / endBinding (elementId + focus + gap).
- Container: add { "type": "arrow", "id": "..." } to the boundElements array (multiple arrows supported).
- Missing either side → the arrow will not smart-snap, and the arrow position stays fixed when the container moves.
Recommended focus parameter calculation(-1 ~ 1):
- 0: snap from the container center (most stable, recommended default).
- Positive value (0~1): biased toward right/down (horizontal arrows biased down, vertical biased right).
- Negative value (-1~0): biased toward left/up.
- Advanced: if the container has different width and height, focus can be fine-tuned to ±0.2~±0.5 to avoid the arrow being pulled from a corner. Extreme ±1 may cause the arrow to stick to the edge but look visually poor.
Recommended gap parameter:
-
0: the arrow endpoint is flush against the container edge (may clip through).
-
8~12: optimal visual gap (recommended value).
-
15: the arrow is too far away, appearing loose.
points / width / height calculation(must be correct when generating):
- The first point of points is always [0, 0].
- Subsequent points are relative offsets (e.g. horizontal arrow [[0,0], [distance, 0]]).
- width = max_x - min_x (the x difference among points).
- height = max_y - min_y。
- Simple straight arrow example: points [[0,0], [150,0]] → width=150, height=0.
- Bent arrow: points [[0,0], [50,50], [150,50]] → width=150, height=50.
Creation order: first create all containers → then create arrows (binding depends on the containers already having IDs). The same applies to text binding: containers first, text after.
Common binding failure debugging(add to "Common errors and debugging"):
- Arrow does not follow when the container is dragged → check whether the container's boundElements is missing the arrow ID.
- Arrow position jumps / does not snap → focus/gap is extreme, or the points width/height calculation is wrong.
- Redraw anomaly after arrow binding → the updated timestamp is not incremented, or versionNonce is duplicated.
- Obsidian rendering arrow is not bound → embed .excalidraw.md to test and confirm the JSON is complete in both directions.
Version compatibility: based on Excalidraw JSON v2 + Obsidian Excalidraw plugin 2.0+ (latest in 2025).
Mandatory constraints for AI generation (to prevent parsing errors)
When using AI to generate Excalidraw JSON files, the following constraints must be strictly followed to prevent parsing errors:
- No comments: the generated JSON code block must not contain
//or/* */comments. - No fake placeholders:
...or(其余内容同上)are strictly prohibited; a complete, valid JSON object must be output. - Negative sign rules: all numeric fields (x, y, width, height) must be numbers. The illegal format
"x": -is prohibited. Negative numbers must have a leading digit (such as-0.5instead of-.5)。 - Code block isolation: JSON data must be wrapped in
json ..., and there must be a complete YAML Frontmatter section above it.
Error Self-Check List (Final Check)
After generating or modifying an Excalidraw file, please check the following items to avoid common errors:
- ID conflicts: Are short random IDs (such as nanoid) used and unique within the current elements array?
- Order (Z-Index): Are background elements at the front of the array? Are text and arrows at the back?
- Seed: Does each element have a unique seed? (If all elements have the same seed, the hand-drawn jitter appearance will be exactly the same, making it look mechanical).
- VersionNonce: Has a random integer been generated for each element?
- Updated: Are the timestamps monotonically increasing?
- Arrow points: Is the first point of the arrow [0,0]?
- BoundElements closed loop: When an arrow points to a container, is the arrow's ID written in the container's boundElements? (bidirectional binding).
- Cascading deletion: When deleting a container, is its bound text also deleted at the same time?
- Image data: When using an image element, is the corresponding DataURL provided in the files object?
- Coordinate calculation: Has Math.round() been used to avoid subpixel blurriness?
- Text alignment: Is lineHeight provided for multi-line text? Is baseline the baseline height of the first line?
Version compatibility issue analysis and solutions
Cause of the problem
-
JSON syntax errors:
- The original SKILL.md file contains comments inside JSON and warning text, which violates JSON syntax rules
- Generated files containing these non-standard contents will cause parsing failures
-
Version differences:
- SKILL.md is based on a newer version of the Excalidraw specification
- Some features may not be supported in older versions
-
Complexity of binding relationships:
- Incorrect bidirectional binding will cause the document to fail to load correctly
- Missing necessary binding declarations will cause a "fake binding" phenomenon
-
Missing required fields:
- Some versions have stricter requirements for required fields
- Missing key fields will cause parsing errors
Solutions
-
Strictly follow the JSON specification:
- Comments are prohibited in the generated JSON file
- Ensure all JSON structures are complete and correctly formatted
- Use validation tools to check JSON syntax
-
Version compatibility strategy:
- For Obsidian Excalidraw plugin version 2.0+, use the following compatible features:
- Keep the
version: 2format - Avoid using element types specific to the latest version
- Use basic binding relationships and avoid complex advanced features
- Keep the
- For Obsidian Excalidraw plugin version 2.0+, use the following compatible features:
-
Simplify binding relationships:
- For basic shapes, complex bidirectional binding may be temporarily omitted
- Ensure the consistency and completeness of binding declarations
- Create elements in the order of "container first, then members"
-
Required field check:
- Ensure each element contains the following fields:
id: unique identifiertype: element typex,y: coordinate positionwidth,height: dimensionsseed: random seedversion: version numberversionNonce: version nonceupdated: timestamp
- Ensure each element contains the following fields:
-
Debugging Tips:
- Start testing with simple shapes
- Gradually add complex elements
- Use a simplified version to verify basic functionality
- Check the browser console for error messages
Recommended Practices
-
Use template files:
- Template files generated based on this SKILL.md
- Ensure the template files have been verified to load correctly
-
Version marking:
- Add version information to the generated files
- Record the Excalidraw specification version used
-
Compatibility testing:
- Test the generated files in different versions of Excalidraw
- Ensure they display correctly in the target version
-
Error handling:
- Provide detailed error messages
- Guide users on how to fix common issues
By following the above solutions, you can ensure that the generated Excalidraw files display correctly in the current version while maintaining forward compatibility.