Undo/Redo System#

Two-layer architecture combining fast local snapshots with Automerge CRDT operation log.

Architecture#

Layer 1: Snapshot-based Local Undo (fast)#

  • Before each operation, capture a JSON snapshot of the entire scene
  • Undo = restore the previous snapshot (< 5ms)
  • Redo = restore the next snapshot
  • Stack-based: undo stack + redo stack

Layer 2: Automerge Operation Log (collaborative)#

  • Every operation is also recorded in the Automerge document
  • Enables collaborative undo (each user undoes their own ops)
  • Persistent across sessions via IndexedDB/R2

Operation Types#

OpRecorded DataUndo Behavior
addtype, id, paramsRemove the added object
translateobjectId, dx, dy, dzReverse the translation
booleanop, idA, idB, resultIdRestore both input objects
deleteobjectId, snapshotRestore deleted object
clearsnapshotRestore entire scene

Grouping#

Related operations are grouped into single undo steps:

  • Adding a primitive + auto-offset = one undo step
  • This prevents partial undos (e.g., object added but not positioned)

Timeline UI#

The timeline strip shows recent operations as clickable chips. Each chip represents one undo step.

UUID Stability#

All objects have stable UUIDs (v4). UUIDs persist through:

  • Translations
  • Scene export/import
  • Undo/redo cycles
  • Cross-tab sync

Performance#

  • Snapshot capture: < 5ms
  • Snapshot restore: < 5ms
  • Scene replay (10 ops): ~200ms