# Arranging widgets on the page itself

*6 August 2026*

An administrator turns on edit mode, drags widgets around the actual forum, and
sees exactly what everybody else will see — but nobody else sees any of it until
they press Save.

## Why not the admin screen that already exists

There is one, and it works: pick an area, reorder a list, save. What it cannot
do is tell you whether the result looks right, because a list of widget names in
an admin panel is not a sidebar. You arrange it, you go and look, you come back
and adjust, and the loop is slow enough that most people arrange it once and
never touch it again.

Doing it on the page removes the loop. That is the whole feature.

## Live for the person moving it, invisible to everybody else

Ernest's words: *"the Admin sees it live and you have to save to publish it."*

That is a draft, and drafts have to survive more than one page. Arranging the
forum index sidebar and then wanting to check the topic page is the normal case,
not an edge one, so the draft cannot live in a JavaScript variable that a
navigation throws away.

**So the draft is on the server, one per administrator.** While edit mode is on:

- every page *that administrator* loads renders from their draft
- every page anybody else loads renders from what is published
- Save applies the draft and clears it
- Discard clears it without applying

One row per administrator, holding the whole arrangement as JSON. It is small,
it is easy to throw away, and two administrators arranging at the same time
cannot overwrite each other's half-finished work — the last one to press Save
wins, which is the same rule the admin screen already has and one people
understand.

## What a drag actually changes

Three things, and nothing else:

- which area a widget is in
- what order it is in within that area
- whether it is shown at all

Everything else about a widget — its title, its settings, who can see it —
stays where it is edited now. A drag is an arrangement, not a configuration
screen, and trying to make it both is how this ends up being a page builder
nobody asked for.

## The parts

**A rail, not a modal.** Edit mode puts a bar across the top of the page with
what state you are in, the unplaced widgets you can drag in, and Save and
Discard. The page underneath stays the page — real posts, real sidebar, real
width — because the entire point is seeing the actual thing.

**Areas outline themselves.** Every widget area on the page gets a dashed
boundary and a name while edit mode is on, including the empty ones. An empty
area is invisible the rest of the time and is exactly where somebody wants to
put something.

**Pointer events, not HTML5 drag-and-drop.** The native API cannot show a
sensible placeholder, has no useful touch story, and its drag image is the
browser's to decide. A pointer-driven sortable is more code and behaves.

**Nothing is destroyed to remove a widget.** Dragging it out drops it back into
the rail as unplaced. `is_enabled` goes false; the widget, its title and its
settings are untouched, and putting it back is a drag rather than a rebuild.

## Rules

🚨 **Edit mode is an administrator's, and the check is on the server on every
request.** The rail is hidden from everybody else, but hiding a control is not a
permission — the endpoints check `is_admin` themselves, and a draft only ever
applies to the person it belongs to.

🚨 **A draft never leaks.** The renderer takes the draft only when the viewer is
the administrator it belongs to *and* edit mode is on. Somebody who leaves edit
mode on for a week and forgets sees their own draft; nobody else ever does.

**Save is one write.** The whole arrangement, in a transaction, so a half-applied
layout is not a state the site can be in.

## Deliberately not doing

**No resizing, no columns, no free placement.** Widgets go in areas the theme
defines, in an order. A grid you can drag anything anywhere in is a page
builder, and Convoro has a Pages module for people who want one.

**No per-page arrangement from here.** A widget's conditions already decide
where it appears, and that is a configuration question with a screen of its own.
Dragging on the topic page arranges the topic area, not "the sidebar of this one
topic".

**No undo history.** Discard throws the whole draft away, which is the undo. A
stack of intermediate states is a lot of machinery for an arrangement somebody
can redo in ten seconds.

---

## The editor was confusing — 2026-08-08

Ernest, after using it: the widget editor is confusing, and specifically —
**a delete X on each widget**, and **a list down the left of every widget
available, grouped by type.** Both are the same complaint in two places:
*what can I do here, and where is it.*

### Removing a widget took three steps and a guess

Removal existed and was reachable only by opening the cog, reading a settings
form you did not want, and finding "Remove widget" in the panel's footer. The
tools row on each widget showed a cog and a grip, so the two visible verbs were
"configure" and "move" — and removing, the thing somebody most often opens the
editor to do, was behind one of them with nothing saying so.

There is now an **X in the tools row**, beside the cog and the grip. Same
endpoint, same confirmation, same undo — Discard still brings it back until the
page is published. What changed is that the verb is visible.

🚨 **Both entry points now call one function taking an id.** The sheet's remove
button read a module-level `currentWidget` set when the sheet opened. A second
caller reading that variable would delete whatever was last *opened* rather
than what was clicked — a real deletion of the wrong thing, silently. The id
travels on the button instead, and `currentWidget` is gone.

### The palette was behind a disclosure

Everything you could add was inside a collapsed `<details>` labelled "Add a
widget". It was already grouped, which is the part that was right; it was
folded away, which is the part that made the editor feel empty. An operator who
never opened it had no way of knowing there were eleven kinds.

It is now a **dock down the left**, open, for the whole time you are arranging.

**The tray moved into it too.** "Not shown anywhere" was in the top rail and
the palette was below it, so the two lists of things-not-on-the-page were in
different places. They are now one column, in two labelled sections, and the
distinction the section above insists on is still drawn — *these exist and are
unplaced* above *these are kinds you can make a new one of* — because dragging
something out and not knowing whether you removed it or destroyed it is still
the failure to avoid.

**Drag is still the only way to place one.** A chip that looked clickable but
was not would be the same complaint again, so the dock says what to do with
them. Click-to-add would have to invent a target area, and inventing one is how
a widget lands somewhere the operator did not look.

⏸ **Keyboard placement is still not possible.** The whole editor is pointer-
only, which was true before this change and is not made worse by it, but it
should be said plainly rather than left to be discovered: the admin screen is
the accessible path to the same result.

### Narrow screens

The dock is fixed to the left above 1100px and the page is inset to make room.
Below that there is not enough width for both, so it becomes a horizontal strip
under the rail — still open, still grouped, scrolled sideways rather than
folded away. Folding it away again on a laptop would undo the whole change.
