Skip to main content

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.

DataPersisted by exportDocument()
JSON Canvas nodesYes
JSON Canvas edgesYes, when connections are installed
Camera and grid settingsYes, under x-lupinum-board
SelectionYes, under x-lupinum-board
Z-order, lock state, visibilityYes, under x-lupinum-board
Active pointer/text interactionNo
Runtime snap guidesNo

Quick export/import

The engine exports the canonical persisted document shape:

ts
// 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' })
}

loadDocument() validates and clones imported data before it changes the board. To keep imports safe on the browser main thread, one document supports up to 10,000 nodes, 20,000 edges, 10,000 selected node IDs, 64 nested JSON levels, 250,000 JSON values, and 8 million string characters. Also limit the raw byte size before calling JSON.parse() when documents come from an untrusted source.


Connections

ts
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:

json
{
  "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-lupinum-board extension

Board-specific metadata that has no JSON Canvas top-level field is stored under x-lupinum-board. Imports still accept the legacy x-vue-board key from 0.1 documents. Exports always use the new key.

Implementation detail

Document structure

json
{
  "nodes": [...],
  "edges": [...],
  "x-lupinum-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

ts
// Replace all state
engine.loadDocument(document, { mode: 'replace' })

// Merge into existing board
engine.loadDocument(document, { mode: 'merge' })
ModeUse 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.