# Design note — widgets

**Dated 2026-08-05. Written before the code, per the provenance practice in
[ROADMAP.md](../../ROADMAP.md#proving-independence).**

---

## What I got wrong

The roadmap said "Page Editor / CMS — custom pages and structured content
beyond forum topics", and I built exactly that: standalone pages at their own
addresses, built from blocks.

That is half of it. Ernest's actual meaning: **the block system is how you put
things on the forum itself** — a sidebar, something above the topic list, a
panel of recent posts. Custom pages are one use of the blocks; decorating the
forum is the other, and it is the one people use daily.

So the pages work is not wasted — the block types, the editor pattern and the
group visibility all carry straight over. What is missing is somewhere to put
blocks other than a page of their own.

## The job to be done

An administrator wants a "who's online" panel down the side of the forum, a
welcome message above the forum list for signed-out visitors, and a list of
recent posts on the topic page. Without editing a template.

## Decision 1 — an area is a named place, and there are few of them

A widget lives in an **area**. Areas are a fixed list, because each one needs a
real place in the markup to render into — an area nobody renders is the same
trap as a menu zone nobody renders.

| Area | Where |
|---|---|
| `sidebar` | A column beside the forum index, a forum, and a topic |
| `index.top` / `index.bottom` | Above and below the forum list |
| `forum.top` | Above a forum's topic list |
| `topic.top` | Above the posts in a topic |
| `footer` | Across the bottom of every page |

They render through the phase 5 hook points, the same as menus. Third-party
areas are possible for the same reason: an extension can render
`@hook('my.area')` and drop widgets into it.

## Decision 2 — the sidebar exists only when something is in it

**No widgets in `sidebar`, no sidebar.** The page stays full width.

This matters more than it sounds. A permanently-present empty column is the
thing that makes a forum look unfinished, and it is why I would not add a
sidebar on my own last time — a sidebar is a claim that something deserves
permanent space. Making it appear only when populated turns that from my
decision into the administrator's, which is where it belongs.

## Decision 3 — widget types are the block types plus the ones only a forum has

The content types carry over unchanged from pages — heading, rich text, image,
video, HTML — because they are the same job and having two implementations of
"a rich text block" would guarantee they drift.

What is new is the forum-native set, which is the actual point of the feature:

| Widget | Shows |
|---|---|
| `stats` | Topics, posts, members, newest member |
| `online` | Who is here now |
| `members` | The newest members, with avatars |
| `topics` | Recent topics, filterable by forum |
| `posters` | Who posts the most |
| `welcome` | A sign-up prompt — **only to guests**, which is the whole point of it |

Every one of these is data already stored. None of them needs a new table.

## Decision 4 — a widget is cheap to render or it does not ship

Widgets appear on every page in their area, so a slow one is slow everywhere.
Each data widget is a single indexed query with a small limit, and the ones
that would not be — "top posters of all time" over a large table — read a
counter column that already exists rather than aggregating on the fly.

Nothing here fans out per row. That rule is why the forum index takes three
queries for its last-post column rather than two per forum, and it applies
harder to something on every page.

## Decision 5 — visibility is the same model, again

Group rows per widget; no rows means everybody; a signed-out visitor counts as
being in the guest group. Identical to menus and pages, deliberately: this is
the third feature to need it and a third vocabulary would be indefensible.

The welcome widget is the case that makes it worth having — a sign-up prompt
shown to people who are already signed in is the single most common way a
forum looks like nobody maintains it.

## Decision 6 — one editor, per area

Pick an area, see what is in it, add, reorder, remove. The same shape as the
menu editor and the page editor, because a third arrangement idiom in one
admin panel would be a worse offence than any of them individually.

## What this does not do

- **No drag between areas.** Moving a widget from the sidebar to the footer is
  rare enough that a dropdown does it, and dragging across two scrolling
  columns is a lot of machinery for that.
- **No per-forum widget sets.** Areas are site-wide for now. Per-forum is a
  real want, and it is a filter on top of this rather than a different design.
- **No custom databases.** Still staged, still needs its own note.
