8.2 KiB
name, description, argument-hint, user-invocable
| name | description | argument-hint | user-invocable |
|---|---|---|---|
| tldraw-file | Create, repair, validate, or generate valid `.tldr` files that tldraw can open. Use when the user asks for a tldraw diagram, `.tldr` file, corrupted tldraw repair, or a diagram they can open in tldraw. | [diagram request, file path, or validation target] | true |
tldraw File
Use this skill when the user asks to create, repair, validate, or generate a tldraw document/file.
Examples:
- "Make me a tldraw diagram"
- "Create a
.tldrfile" - "tldraw says this file is corrupted"
- "Generate a diagram I can open in tldraw"
Core Rule
Do not hand-wave validity. A .tldr file must be validated with tldraw's own schema/importer, not just JSON.parse.
A file can be valid JSON and still be corrupted to tldraw.
Temporary Setup
If the current project does not already depend on tldraw, install it in /tmp/opencode, not in the user's repo.
# Work outside the repo
bun init -y
bun add tldraw
Use /tmp/opencode as the working directory for validation scripts.
.tldr File Shape
A current .tldr JSON file has this top-level shape:
{
"tldrawFileFormatVersion": 1,
"schema": {
"schemaVersion": 2,
"sequences": {
"com.tldraw.store": 5,
"com.tldraw.asset": 1,
"com.tldraw.camera": 1,
"com.tldraw.document": 2,
"com.tldraw.instance": 26,
"com.tldraw.instance_page_state": 5,
"com.tldraw.page": 1,
"com.tldraw.instance_presence": 6,
"com.tldraw.pointer": 1,
"com.tldraw.shape": 4,
"com.tldraw.user": 1,
"com.tldraw.asset.image": 6,
"com.tldraw.asset.video": 5,
"com.tldraw.asset.bookmark": 2,
"com.tldraw.shape.arrow": 8,
"com.tldraw.shape.bookmark": 2,
"com.tldraw.shape.draw": 4,
"com.tldraw.shape.embed": 4,
"com.tldraw.shape.frame": 1,
"com.tldraw.shape.geo": 11,
"com.tldraw.shape.group": 0,
"com.tldraw.shape.highlight": 3,
"com.tldraw.shape.image": 5,
"com.tldraw.shape.line": 5,
"com.tldraw.shape.note": 12,
"com.tldraw.shape.text": 4,
"com.tldraw.shape.video": 4,
"com.tldraw.binding.arrow": 1
}
},
"records": []
}
Records must be an array of valid tldraw records. Each record needs at least:
{
"id": "shape:example",
"typeName": "shape"
}
Actual records must also satisfy their shape-specific schema.
Required Base Records
Include at least:
{
"gridSize": 10,
"name": "",
"meta": {},
"id": "document:document",
"typeName": "document"
}
{
"id": "page:page",
"name": "Page",
"index": "a1",
"meta": {},
"typeName": "page"
}
Every shape should have:
{
"parentId": "page:page",
"index": "a2",
"typeName": "shape"
}
Rich Text
Use tldraw rich text for labels.
Helper shape:
{
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Label"
}
]
}
]
}
For compatibility, also include the legacy text prop with the same plain text.
Geo Shape Template
Use geo shapes for most boxes. They are easier than notes and less fragile.
{
"x": 100,
"y": 100,
"rotation": 0,
"isLocked": false,
"opacity": 1,
"meta": {},
"id": "shape:box",
"type": "geo",
"props": {
"geo": "rectangle",
"w": 260,
"h": 90,
"color": "blue",
"labelColor": "black",
"fill": "solid",
"dash": "solid",
"size": "m",
"font": "sans",
"align": "middle",
"verticalAlign": "middle",
"growY": 0,
"url": "",
"scale": 1,
"richText": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "My box"
}
]
}
]
},
"text": "My box"
},
"parentId": "page:page",
"index": "a2",
"typeName": "shape"
}
Text Shape Template
{
"x": 100,
"y": 40,
"rotation": 0,
"isLocked": false,
"opacity": 1,
"meta": {},
"id": "shape:title",
"type": "text",
"props": {
"color": "black",
"size": "xl",
"font": "sans",
"textAlign": "start",
"autoSize": true,
"w": 900,
"scale": 1,
"richText": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Diagram Title"
}
]
}
]
},
"text": "Diagram Title"
},
"parentId": "page:page",
"index": "a1",
"typeName": "shape"
}
Arrow Shape Template
Arrows require labelColor. Missing it can make tldraw report the file as corrupted.
{
"x": 400,
"y": 200,
"rotation": 0,
"isLocked": false,
"opacity": 1,
"meta": {},
"id": "shape:arrow",
"type": "arrow",
"props": {
"kind": "arc",
"color": "black",
"labelColor": "black",
"fill": "none",
"dash": "solid",
"size": "m",
"arrowheadStart": "none",
"arrowheadEnd": "arrow",
"bend": 0,
"start": {
"x": 0,
"y": 0
},
"end": {
"x": 120,
"y": 0
},
"labelPosition": 0.5,
"font": "sans",
"scale": 1,
"richText": {
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "label"
}
]
}
]
},
"text": "label"
},
"parentId": "page:page",
"index": "a3",
"typeName": "shape"
}
Valid Colors
For color and labelColor, use only known tldraw colors:
blackgreylight-violetvioletbluelight-blueyelloworangegreenlight-greenlight-redredwhite
Invalid or missing labelColor can corrupt the file.
Notes
Avoid note shapes unless you know the current schema. They require additional props and are more version-sensitive. Prefer geo rectangles with fill: solid or fill: semi.
Validation
First validate JSON syntax:
bun -e "const f='/path/to/file.tldr'; const data=await Bun.file(f).text(); JSON.parse(data); console.log('valid json')"
Then validate with tldraw's store/schema:
bun -e "import { createTLStore } from 'tldraw'; const file=JSON.parse(await Bun.file('/path/to/file.tldr').text()); const snapshot={store:Object.fromEntries(file.records.map(r=>[r.id,r])), schema:file.schema}; try { const store=createTLStore({snapshot}); console.log('ok records', store.allRecords().length); } catch(e){ console.error(e); process.exit(1)} process.exit(0)"
Finally validate with the same importer path tldraw uses for .tldr files:
bun -e "import { createTLStore } from 'tldraw'; import { parseTldrawJsonFile } from './node_modules/tldraw/dist-esm/lib/utils/tldr/file.mjs'; const json=await Bun.file('/path/to/file.tldr').text(); const schema=createTLStore().schema; const result=parseTldrawJsonFile({json, schema}); console.log(result.ok ? 'parse ok' : result.error); process.exit(result.ok ? 0 : 1)"
Run importer validation from the temp directory where tldraw is installed, for example /tmp/opencode.
Common Corruption Causes
- File is valid JSON but does not match tldraw schema.
- Missing
labelColoron arrow shapes. - Missing required shape props for note shapes.
- Old schema sequence numbers copied from another tldraw version.
- Invalid color names.
- Shape
parentIdpoints to a missing page. - Duplicate record IDs.
- Records object used instead of records array in
.tldrfile format. richTextmissing where current schemas expect it.
Recommended Workflow
- Create or update
.tldrwithapply_patch. - Run JSON validation.
- Run
createTLStore({ snapshot })validation. - Run
parseTldrawJsonFilevalidation. - If tldraw says corrupted, trust tldraw and inspect the validation error path.
- Fix the specific schema path, not just the JSON.
Practical Diagram Advice
- Use geo rectangles for sections and entities.
- Use text for headings.
- Use simple arrow shapes for flow.
- Keep IDs stable and readable:
shape:admin-review,shape:stream-category. - Use indexed records like
a1,a2,a3. - Keep diagrams editable rather than pixel-perfect.