# Pages, as a CMS

2026-08-08. Asked for directly:

> "Pages needs to be a full fledged CMS just like the Invision version. So if
> we need to rework it let's build it."

This is a gap analysis before any code, because "full fledged CMS" is a phrase
that hides three months of work if it is not counted.

---

## What Pages already is

More than it looks. Today it has:

- **Pages** — slug, title, draft/scheduled/published, per-page width, meta
  title and description, indexable flag, group restrictions.
- **Blocks** — a page is composed of blocks rather than being one blob of HTML.
- **Custom databases** — a database has fields of typed kinds, records with
  JSON values, a title field, a sort field and direction, per-field group
  visibility, and list and detail views.
- **The root namespace** — a page or a database record can live at `/whatever`,
  and one route dispatches between them.

That is genuinely most of a CMS. What follows is what is missing, in the order
the absence actually hurts.

## The gaps, counted

### 1. 🚨 A record cannot be commented on, and a page cannot either

Every other application got comments through System's `discussions` — Blog
first, then Events, which is what proved the seam. Pages is the odd one out,
and a custom database is *exactly* the case people build article sites on.

This is now cheap: `open('page_record', $id, …)`. It should have been done
when `discussions` existed.

### 2. 🚨 There is no menu, no category, and no way to browse

A database lists its records and that is all. Invision's Pages has categories
within a database, and without them a database of four hundred articles is one
list four hundred rows long. **Categories, one level, on the database.**

Deliberately one level. Nested categories mean a tree, a breadcrumb that can be
arbitrarily deep, and a "move this category" screen that has to refuse cycles —
and nobody has asked for depth, only for grouping.

### 3. Templates per database

Invision lets an operator write the listing and the record template. That is
the single biggest thing "a CMS" means to somebody coming from it, and it is
also the biggest security surface in this note: an operator-authored template
is code. Convoro already has a template compiler and an admin who can edit
themes, so the machinery exists — but the answer is *not* to hand `.cvr` to a
form. See below.

### 4. Revisions

A CMS keeps what a page said last week. Not because anybody reads history for
fun, but because "put it back" is the thing people need at the worst moment.

### 5. Smaller, but each one is somebody's day

- **A page cannot be duplicated.** Copying a layout is how people build the
  second, third and fourth page.
- **A record has no author display, no view count, no "related".**
- **A database has no RSS feed**, and an article site without a feed is a site
  people cannot follow.
- **There is no reordering** of blocks except by editing.

## 🚨 What this note refuses

**Operator-authored PHP templates.** Invision's Pages lets an administrator
write template code that runs on the server. That is a remote-code-execution
hole with a login form in front of it, and it is the single most common way an
Invision site gets owned — a compromised administrator account becomes a shell.

Convoro will not ship that. What it ships instead:

- **A field-placement editor**: the operator chooses which fields appear, in
  what order, in which of a few provided layouts. Covers the overwhelming
  majority of what people actually do with a custom template.
- **The existing block system** for anything more, because a block is a
  registered kind with a renderer somebody wrote in a module — code review, not
  a textarea.

This is a real capability difference and it should be stated to anybody
migrating, not discovered. It is a deliberate trade: a site that cannot be
owned through its own admin panel, in exchange for a layout that stops at what
the placement editor can express.

## Order

1. **Comments on records and pages** — small, and it closes the odd-one-out.
2. **Categories** — the one that makes a real database usable.
3. **Revisions** — on pages and records, one table, restore by writing a new
   revision rather than deleting forward.
4. **Field placement** — the honest answer to "custom templates".
5. **Feeds, duplication, reordering** — a day each, and none of them blocks
   anything.

## What this note does not decide

- **Whether a record can belong to more than one category.** Tags already
  exist and already attach to topics; if a record wants many labels that is
  probably tags rather than categories.
- **Whether revisions are kept forever.** They are rows and rows grow; a
  retention setting is a real question and not one to guess at.
- **Cross-database relationships.** Invision has them. They are a big feature
  and nobody has asked.
