Skip to main content

The editor

The editor is a separate mode, not a separate site. Your client edits the real page, with the real styles, at the real URL.

How it loads

  1. A visitor loads a page → server-rendered plain text, zero editor JS.
  2. The client visits /admin and signs in.
  3. With a session present, the editor bundle lazy-loads on subsequent page loads.

Server Components render editing anchors that cost a visitor nothing, because they only exist in editor mode:

<span data-copy-field="heroTitle" data-copy-scope="about">Hello!</span>

Editing a field

Editing happens through a click-to-open popover, not contenteditable — which fights paste-with-styles, IME input, mobile keyboards and React's controlled inputs. The popover gives most of the perceived magic for a fraction of the bugs.

  • Text — a single-line or multiline input, respecting maxLength.
  • Rich text — a Markdown editor with the allowed formatting only.
  • Image — upload, or paste a URL from an allowed host.

A field referenced in JSX but absent from the YAML renders as nothing in production and shows a labelled placeholder in editor mode, so the client has something to click. A locked field is visible but not editable.

True in-place editing is a v2 upgrade, not a v1 omission.

Edit mode and view mode

Editing intercepts clicks. That is the point — but it also means a link whose own text is a <Copy> field cannot be followed, which is most site navigation:

<Link href="/about"><Copy field="nav.about" scope="_global" /></Link>

So the toolbar carries a mode switch.

EditClicking text opens its popover. The default.
ViewThe page is handed back to the site: links, menus, dropdowns and forms all behave as a visitor's.

View mode is not a sign-out. The toolbar stays, the changeset survives, and pending edits are still applied to the page — so it doubles as a preview of the site as it will read once published, without the outlines.

The mode is remembered for the browser session, so switching to View and clicking through three pages does not drop you back into Edit at each one.

Hold (Ctrl on Windows and Linux) and click. The click goes straight to the page, so the browser opens the link in a new tab — which is the safer default here, since the tab you are editing in keeps its pending changes.

While the modifier is held, the editing outlines drop away, so it is visible before the click lands that the page will get it.

Any click the browser already treats specially — Shift, Alt, middle-click — passes through the same way.

The floating toolbar

Edit / ViewWhether clicking a field edits it or uses the site
Current pageOpens the Content panel — where you are, and the way elsewhere
Locale switcherEdit another locale of the same page
Changeset badgeHow many changes are pending
PublishReview and commit

The Content panel

Pages and collections in one panel, because finding something and going to it should be one gesture rather than two panels and a guess.

  • Left — every page with content, as a tree, with the one you are on marked. Clicking navigates. Below it, the site's collections.
  • Right — the selected collection's items: Open, hide/publish via _draft, reorder, delete, and New item.
  • Top — a filter across both. Searching flattens the page tree, since a result list is not a hierarchy.

Open is what makes an item reachable. It needs to know the route that renders one, which copy-ink types derives from your JSX — see Opening an item. Until types has run there is no Open button, and the panel says why.

Item creation is driven entirely by the collection schema: slugs are generated from slugFrom, checked for uniqueness, and editable before the first save. Editing an item still happens on its page, by clicking the text — the panel gets you there and manages which items exist.

Publishing

Edits accumulate client-side for the whole session and leave as one commit. There is a before/after diff preview first.

Editing a value back to its original drops the change entirely, so the "3 changes" badge never overstates.

After publishing, the UI says:

Published — live in about 2 minutes.

Commit → rebuild → deploy takes a while, and unexplained that reads as broken. Do not remove that messaging.

Concurrency

The changeset carries the base commit SHA. If the branch has moved, the write is rejected:

Someone else changed this page — reload.

There is no merging in v1. For a single-client site this effectively never fires; for a site where two people edit at once, it fires and it is the honest outcome.

Losing work

Optimistic state survives navigation within a session. A full reload loses it, and the editor warns before one.

What a client can and cannot do

CanCannot
Edit any unlocked field on any pageCreate pages
Use the site normally in view modeSign in without being on the allowlist
Create, reorder, hide and delete collection itemsChange a slug after the first save
Upload images and paste allowed remote URLsAdd an image host
Switch locale and edit translationsEdit locked fields
Publish, once, per session's worth of changesMerge concurrent edits

The line is: the client edits on the real page, and never creates pages.

Briefing your client

Three things are worth saying out loud when you hand a site over:

  1. Changes go live a couple of minutes after Publish. Not instantly.
  2. Nothing is saved until Publish. Reloading loses pending edits.
  3. If it says someone else changed this page, reload and redo. It is not lost data; it is a refusal to overwrite.