Step 1: What you're building
A world with cards, a map and a couple of notes in it — turned into a site, live, right here.
Let's say you're making a world where you're running a campaign and you needed your players to be able to read the lore between sessions — who Aria of the North is, what's actually in the Sunken Vale, why the Cartographers' Guild wants the Salt Road watched — without you retyping any of it into a doc, and without handing them edit access to the world itself. Here's how you build that.
That's a wiki: an app that reads a world instead of storing content of its own, and turns whatever's already there into pages a reader can open with no account at all. Here's the code for one, and it running against a small example world right below it:
import { useMemo } from "react"
import { useWorldMeta, useWorldQuery } from "@vvd/sdk"
function WikiFrontPage() {
const world = useWorldMeta()
const docs = useWorldQuery("documents")
// Cards are the entries. Everything else — maps, notes, tables — goes on a shelf below.
const entries = useMemo(
() => docs.filter((d) => d.documentType === "card" && d.isViewable !== false),
[docs],
)
const extras = useMemo(
() => docs.filter((d) => d.documentType !== "card" && d.isViewable !== false),
[docs],
)
return (
<>
<header>
<strong>{world?.name ?? "An encyclopedia"}</strong>
<span>{entries.length} entries · {extras.length} other documents</span>
</header>
<section>
<h2>Entries</h2>
{entries.map((entry) => <p key={entry.id}>{entry.name}</p>)}
</section>
<section>
<h2>Also in this world</h2>
{extras.map((doc) => <span key={doc.id}>{doc.name} · {doc.documentType}</span>)}
</section>
</>
)
}Nobody typed that index, and nothing in it would change if this world had four hundred
documents instead of six. That's the whole idea, and it's real: this is reading through the
same world capability a published edition answers from — not a mock-up.
You will learn
- Which four manifest lines turn an ordinary app into a wiki
- How to turn the documents already in a world into entries, live, with no content of your own
- How to offer a theme catalog and let an owner rearrange the page, without building either UI
- What Publish actually freezes, and who can see the result
- How to put your own domain on it
How this build works
You'll scaffold a wiki with the CLI, then build up its page one small piece at a time — reading the world, picking a theme, letting the owner edit — ending with it live on the internet.
One honest thing up front, so you only have to read it once: a wiki is an app
(defineApp, owning a route), and this page's playground can only mount tools
(defineTool, editing one document) — an app needs the real host and the real vvd run.
So every editable step below wraps the exact same page logic — the same hooks, the same
reads — inside a small defineTool stand-in, purely so you can run it and edit it right
here. The scaffold you get in the next step wraps that same logic in defineApp instead;
nothing about the logic itself changes. Where a step genuinely can't run in this sandbox at
all — publishing, a real domain — it says so plainly instead of faking a preview.