Repository navigation
v0.49.0
Features
edit speaks operations vocabulary v2
@templatical/template-tools
template-tools edit applies the operations the editor, collaboration backends and Templatical Cloud share — {"op": "updateBlock", "blockId": "…", "set": {…}} and the rest — with the engine from @templatical/types, and a refusal names the operation, its code and the reason. The package re-exports applyOperations, OperationError and getColumnCount.
Breaking changes:
- The
{ "operation", "data" }form is refused, with a pointer to the new one. applyOperationandOperationResultare removed; useapplyOperationsand catchOperationError.updateBlockStyleis gone:updateBlock'ssetreplacesstyleswhole, so send the block's fullstylesobject with the property changed.
Operations vocabulary v2, the engine that applies it, and the collaboration contract
@templatical/types
applyOperations(content, ops, { locks, session })applies a batch of operations —addBlock,moveBlock,deleteBlock,updateBlock,updateSettings,setContent— to a copy, in order and all or nothing, and throws anOperationError(code,opIndex) at the first one it refuses. Positions are anchored to a sibling id,updateBlock/updateSettingstakesetandunset, andexpectpreconditions guard a change against the content having moved on.applyOperationsInPlace,getColumnCountanddeepEqualcome with it. Templatical Cloud's engine follows the same rules, pinned by the shared cases intests/fixtures/operations/(regenerate their manifest withpnpm --filter @templatical/types run fixtures:manifest).- The bring-your-own collaboration contract:
CollaborationProvider(join,submit,operationsAfter, and optionallyacquireLock/renewLock/releaseLock),CollaborationHandlers,OperationBatch,RevisionedBatch,CollaborationActor,CollaborationMember,BlockLock,BlockLockHolder,CollaborationRemoteChange, andCollaborationConflict, anSdkErrorwithcode,opIndex,holderandholders. CollaborationActor.clientis the agent's name on anmcpactor (Claude,Cursor, …). A collaboration backend that lets agents edit sends it with each agent batch, and the editor names it in a notice.CollaborationHandlers.onResync(revision, actor?): the optionalactoris who caused the re-sync. The editor names an agent's re-sync in a notice.Templategainsrevisionandlocks.SdkErrortakes an optional third argument,code(SdkErrorCode): the error's code, asCollaborationConflictcarries it.SdkErrorCodeis exported from@templatical/typesand@templatical/editor.
Breaking changes:
TemplateOperationandTemplateOperationPayload(the v1 vocabulary) are removed; useOperation.
Real-time collaboration in the editor over your backend, and agents' edits named
@templatical/editor
init({ collaboration })collaborates over anyCollaborationProvider(it needstemplates, whoseloadreturns the template'srevision). Every edit is sent as operations; other people's edits appear on the canvas in order; selecting a block locks it, and others' locked blocks show their holder's name and colour and can't be selected; the header shows who else is here, one avatar per person; undo and redo cover your own edits and skip, with a notice, a step someone else has overtaken.init({ onRemoteChange })reports another session's edits.- With a collaboration provider,
templates.savereceives only renames, after the editor's batches are confirmed; a version preview pauses collaboration, and a restore re-syncs from the backend and names the people whose locks refuse it. - The merge-tag tokens in another session's batch — an AI agent's, another editor's, a server's — become tags as the batch arrives, the way loaded content's do, and nothing is sent back for it.
- A batch from an agent (
actor.type: "mcp") shows a notice — "Claude for Ada changed 3 blocks", or the template settings — and outlines the changed blocks for 2 seconds, held still under reduced motion. An agent's re-sync reads "Claude for Ada updated the template". Batches and re-syncs from one agent within 2 seconds share a notice. - The bar, lock outlines and notices are translated into all eight locales.
- The collaboration contract's types (
CollaborationProvider,CollaborationHandlers,Operation,OperationBatch,RevisionedBatch,BlockLock, …) are re-exported from@templatical/editor.
Breaking changes:
- The
history.collabWarningstring is gone.
Real-time collaboration over a provider
@templatical/core
useCollaboration({ provider, loadTemplate })runs a collaboration session over anyCollaborationProvider: it captures the editor's changes as operation batches (diffContent), sends one batch at a time with retries under the samebatchId, applies other sessions' batches strictly in revision order with its own pending ones replayed on top, catches up throughoperationsAfter, takes the selected block's lock, tracks presence, and keeps undo and redo as guarded inverse batches (invertOperations) that a backend can refuse.diffContent(before, after)andinvertOperations(before, ops)are exported for headless use.useCollaboration({ normalizeRemoteOperations })rewrites another session's batch, live or from a catch-up, just before it is applied, given the content it applies to. The editor uses it to turn merge-tag tokens into tags.onRemoteChangereceives the batch as the backend sent it.- Other sessions' batches apply without their
expectpreconditions: the backend already checked them against its own copy, which can differ from this one in merge-tag markup alone. Any other refusal re-syncs. useCollaboration({ onRemoteResync })says who caused a re-sync, when the backend passesonResyncan actor, before the editor catches up.
Breaking changes:
useHistoryno longer takesisRemoteOperation.
All 15 @templatical/* packages are published at 0.49.0 — they share one version number.
Full changelog: https://docs.templatical.com/changelog