Skip to content
Wiki— browse docs
On this page

Step 6: Arrange navigation

Let the owner reorder the page, and never build a link yourself.

A wiki someone can't link into isn't much of a wiki. Two separate things make that work: the order of what's on the page, which you own, and the address of each entry, which the platform owns.

Section order

Keep it in a field.list and two owners reordering at once both land — it's positional, so there's nothing to race.

Edit the tool below. Add a move button and watch the order change live:

actions.list("order").move(from, to)
Drag Featured above All entries
src/app.tsx Lines 21 to 23 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: an ↑ button appear on every row but the first; click one and it swaps places with the row above, instantly.

Note:

The scaffold's real field starts empty, not seeded — an empty list means "the default order," so a fourth section you add later lands in the right place for everyone who never touched the order. Reference has the one-line fallback that makes that work.

Entry addresses — never build one yourself

Your bake (Step 7) assigns each document a route, edition-relative. Prefixing it for where the page is actually served — a subdomain root, a path mount — depends on context your code doesn't have. Ask the nav capability instead, and it answers correctly on both the live host and the published one:

const nav = useHostCapability("nav")

nav.hrefFor({ worldId, documentId })     // a ready-to-use href, or null
nav.openDocument({ worldId, documentId }) // go there

hrefFor returns null for a document that isn't in this edition — your cue to render a plain label instead of a dead link.

Warning:

entryPath is a resolved document id, never the raw segment

When someone lands on /sera-vale, the platform resolves that segment against the edition's baked index — a bare slug, the combined "name-slug" form site themes link with, or a raw document id all match — and hands your renderBaked the document id it resolved to as entryPath (null means the home page). A segment it can't resolve 404s before your render ever mounts, so you never see a raw path. The id clause is therefore the one that opens the entry; accepting the slug too costs one clause and keeps the same lookup working anywhere it's handed a path instead of an id:

const hit = docs.find((d) => d.id === entryPath || (d.slug ?? d.id) === entryPath)

One world has one address, and reserved first segments (api, _next, auth, worlds…) never reach a published site — an entry whose slug collides with one is unreachable at the top level. Reference has the full list and the /<a>/<b> resolution rule.

Recap

  • Section order lives in a field.list; two owners reordering at once both land.
  • nav.hrefFor / nav.openDocument are the only correct way to link to a document — never build the URL yourself.
  • entryPath is the resolved document id (null = the home page); a segment the platform can't resolve 404s before renderBaked mounts.

Next steps