Skip to content
Wiki— browse docs
On this page

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:

src/app.tsx
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>
    </>
  )
}
A wiki's front page, live
Running on example data.
Starting the example…

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.