Skip to content
Apps— browse docs
On this page

Step 3: Give it shared state

One hook, no coordinates — the host already knows where this mount's document lives.

A tool you built in Getting Started opens its state with useDocument(coords, codec) — you hand it a document id, it hands back data. An app's own state skips the coordinates entirely, because the host already knows the answer: one document per world, per app, per project.

Edit the board below. Replace the empty function Board() with one that reads data.blocks through useCollabState:

import { field, useCollabState } from "@vvd/sdk"

function Board() {
  const { data, actions } = useCollabState({ blocks: field.map<Block>() })
  if (!data || !actions) return null
  // … same rendering as before, reading data.blocks instead of nothing
}
Add the blocks field
src/app.tsx Line 1 highlighted.

Edit and the example re-runs. Tab indents; press Escape to leave the editor.

Running · your edits, live
Starting the example…

You should see: nothing changes — the map is empty, so every block still falls back to its default spot. That's expected. What changed is underneath: data.blocks is now a real collaborative field, not a constant, and the moment something writes to it, this view is already reading the right place.

Tip:

No coordinates, and that's the whole point

Compare this to useDocument(coords, codec) from Getting Started — that hook needed a document id because a tool's document could be any document. An app's own state only ever means one thing: this mount's state. The host resolves "which document" for you, keyed by world, app, and — you'll feel the reason for that third key in Step 5 — project. State, routes and tabs has the full picture.

Next steps