Skip to content
Apps— browse docs
On this page

Step 4: Pin the world

A pinboard is a list of ids in your own state, pointing at documents you don't own.

A pinboard doesn't need new documents — it needs a list of ids pointing at documents that already exist, plus a way to open one. Add a second field to the same shared state, and read the world alongside it:

const { data, actions } = useCollabState({
  headline: field.value<string>("Welcome — make this place yours."),
  pinnedIds: field.list<string>(),
})
const docs = useWorldQuery("documents")

useWorldQuery("documents") is live — it re-renders as the world's catalog changes on any client, the same way useCollabState is live for the headline. Reading it takes one declaration: needs: ["world"] on the tool, because needs is your consent surface — refs and nav are always present, but reading the world must be asked for.

Pin "Aria of the North" with actions.list("pinnedIds").push(id); open it by resolving its id through the refs capability and handing the result to nav:

A pinboard
src/app.tsx Lines 23 and 51 to 64 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: every document in the world listed under the headline, each with a star. Click "Aria of the North" — it fills in and stays filled after you click elsewhere. Click it again to unpin.

Note:

A reference, never a copy

pinnedIds holds ids, not documents. Pin "Aria of the North" and you've written one string into your app's own state — the card itself still lives where it always did, still owned by whoever owns it, still visible to whoever could see it before. Rename the card in the editor and the pinned chip's label follows, because it's reading the same row useWorldQuery already gave you.

Next steps