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
}Edit and the example re-runs. Tab indents; press Escape to leave the editor.
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.
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.