Serialization
Export and import boards with the engine's JSON Canvas document API.
Save and load boards as JSON Canvas documents. Runtime snapshots are for rendering and tests; persisted documents go through engine.exportDocument() and engine.loadDocument().
What to persist
Persist the object returned by engine.exportDocument(). Serialize it when your storage requires a string. Do not persist
getState(), Vue refs, or DOM state.
| Data | Persisted by exportDocument() |
|---|---|
| JSON Canvas nodes | Yes |
| JSON Canvas edges | Yes, when connections are installed |
| Camera and grid settings | Yes, under x-vue-board |
| Selection | Yes, under x-vue-board |
| Z-order, lock state, visibility | Yes, under x-vue-board |
| Active pointer/text interaction | No |
| Runtime snap guides | No |
Quick export/import
The engine exports the canonical persisted document shape:
// Export
const document = engine.exportDocument()
localStorage.setItem('board', JSON.stringify(document))
// Import
const stored = localStorage.getItem('board')
if (stored) {
engine.loadDocument(JSON.parse(stored), { mode: 'replace' })
}Connections
const engine = createBoardEngine({
plugins: [connectionsPlugin()],
})
const document = engine.exportDocument()
engine.loadDocument(document, { mode: 'replace' })Install the same first-party plugins before importing documents that use them. When the connections plugin is installed, it owns edge export and import. Core validates the JSON Canvas document and passes plugin-owned fields to installed plugins; core does not persist hidden connection state by itself.
Node colors
Node colors are exported as top-level JSON Canvas node color fields:
{
"id": "card-1",
"type": "text",
"x": 80,
"y": 80,
"width": 260,
"height": 140,
"color": "5",
"text": "Draft release notes"
}Import accepts valid preset IDs and six-digit hex colors into BoardNode.color. Edge colors stay on JSON Canvas edge records owned by the connections package.
The x-vue-board extension
Board-specific metadata that has no JSON Canvas top-level field is stored under x-vue-board. That includes camera, grid, z-order, lock state, visibility, hierarchy, and plugin-owned metadata.
Implementation detail
Document structure
{
"nodes": [...],
"edges": [...],
"x-vue-board": {
"camera": { "x": 0, "y": 0, "z": 1 },
"grid": { "size": 20, "majorEvery": 5, "snap": true, "pattern": "line" },
"nextZIndex": 5,
"nodes": {
"node-1": { "zIndex": 1, "locked": false, "visible": true },
"node-2": { "zIndex": 2, "parentId": "group-1" }
}
}
}Import modes
// Replace all state
engine.loadDocument(document, { mode: 'replace' })
// Merge into existing board
engine.loadDocument(document, { mode: 'merge' })| Mode | Use when |
|---|---|
'replace' | Loading a saved board document or resetting the whole scene. |
'merge' | Importing another document into the current board without clearing it. |
loadDocument() validates the document. Invalid node fields, invalid node colors,
missing edge endpoints, or unsupported plugin-owned edge data fail the import
instead of silently creating a partial board.