Skip to content

Create a page and its Main Subject in one step - #1374

Draft
malberts wants to merge 16 commits into
masterfrom
page-first-subject-creation
Draft

Create a page and its Main Subject in one step#1374
malberts wants to merge 16 commits into
masterfrom
page-first-subject-creation

Conversation

@malberts

@malberts malberts commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #1355

A Subject could only be created from a page that already existed: create the page, name it, open Create subject,
pick the Schema, name the Subject again. Nothing said the page was a prerequisite, and users who think in entities
expected Create subject to create the thing itself.

What it does

Schema-first creation, with the page created on the way:

  • Special:CreateSubject opens the Subject creator with a Page field: matching existing pages plus "Use X as a new
    page". A subpage pins the Schema (Special:CreateSubject/Person).
  • A Create Person call to action below the description of Schema:Person (named after each Schema), leading
    there with the Schema pinned.
  • Create subject in the sidebar links there from every page. The page tool that adds a Subject to the page being
    viewed is now called Create subject here, and the Data tab's button Create subject, so every entry uses
    one verb.

Picking a page that exists adds the Subject to it: as its Main Subject when it has none, otherwise alongside the one
it has, which the dialog names. A new page is created empty on save and the Subject becomes its Main Subject; the
browser then lands on that page.

Decisions worth challenging

The label is not copied from the page title. A Main Subject without a label already displays as its page name
(ADR 31), and a stored copy would be exactly the default that ADR removed: it cannot be told from a chosen label, so
a page move would stop renaming the Subject. The page title is the required input; the label stays optional.

Two writes, not one endpoint. The page is created through MediaWiki's own API and the Subject through the
existing endpoint, as the move dialog does. Core enforces createpage, nothing is written until save, and the page id
is kept so a retry after a failed Subject write does not create the page twice. The cost is an empty page when that
retry never comes, and two recent-changes entries. A NeoWiki endpoint writing both slots in one revision is the
follow-up if that bites.

The page picker rather than a title field. A title collision becomes a visible choice between the existing page
and a new one, instead of a silent merge or an error.

A link rather than an in-place dialog on Schema pages. One mount point, and a URL that later entry points (red
links, in-flow creation) can reuse.

A special page rather than a sidebar link that opens the dialog in place. The frontend bundle (Vue, Codex,
Pinia and NeoWiki's own code) is loaded only on content, Schema, Layout and Mapping pages and on NeoWiki's special
pages. Anywhere else the link would first have to load all of that before a dialog could open, so a page that loads
it is the plain, reliable path. The URL is also what makes the entry point placeable: [[Special:CreateSubject/Person]]
works in any page, template or MediaWiki:Sidebar without JavaScript, and it is what the red-link affordance for
missing relation targets (#1120) can point at. Opening the dialog in
place where the bundle is already loaded is a possible follow-up, not a change of approach.

The special page is restricted to edit and refuses users without createpage. A special page names one
restriction; edit is the one the Subject write needs and the one anonymous users lack on hosted wikis, so the page is
hidden from them. The sidebar link and the Schema page button require the same pair of rights.

Considered, omitted

  • Prefilling the page title from a URL parameter.
  • Edit notices for the chosen page.
  • Locking a pinned Schema; the back button still reaches the picker.

Screenshots (UI, Playwright)

Sidebar on a content page. The page tool now reads "Create subject here"; "Create subject" is the new link to the special page. sidebar-create-subject
Schema page. "Create Person" below the description, with the pencil alone in the corner. [SCREENSHOT: schema-page-create-button.png]
Special:CreateSubject/Person. The dialog on the Person step, with a new page chosen in the Page field. special-createsubject-dialog
The created page. Its Main Subject rendered as the infobox under the page name. created-page-infobox
An existing page chosen. The notice naming the page's Main Subject; the new Subject is added alongside it. existing-page-notice

Testing

Vitest covers the creator's page-first mode (page required, new page created then written as Main Subject, existing
page with and without a Main Subject, retry without a second creation, the taken-title error), the special page's
frontend, the Schema page button and its permission hint, and the shared page creation. PHPUnit covers the special
page (mount point, subpage normalization, both refusals) and the sidebar link and its gate. The save path's guards
(the page and tier decided when the save started, no second submit while one is in flight, stale reads of a page the
user moved off) each have a test that fails without them.

AI-authored — Claude Code, Fable 5.1 (high); one-line ask from @malberts, design proposals approved without changes, one mid-task instruction on process; diff reviewed by two Opus subagent passes (code review, mutation-checked test review) with their findings applied, not yet human-reviewed; vitest, phpcs, phpstan and the full PHPUnit suite pass locally, Playwright check on the dev stack with screenshots, CI pending.

malberts and others added 12 commits September 8, 2026 08:37
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The subpage arrives as a DBkey, so a link to Special:CreateSubject/Legal Entity
pinned "Legal_Entity" as the Schema name. Resolve it through the title factory
into the Schema namespace and emit the text form, which also drops a subpage
that names no title at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The page picker stays live across the awaits in handleSave, so a keystroke
during a save could null the choice out from under the writes and turn a
Subject that had been created into an error notification. The choice is now
taken once, up front, and passed to the helpers that create the page and leave
for it. A second save while one is in flight is ignored.

Whether the chosen page has a Main Subject is tracked on its own rather than
inferred from having a name to show for one, so a failed read of that page's
Subjects no longer silently creates a second Main Subject for the server to
refuse. The failed read is reported at the page field and the save waits for
the page to be picked again.

The sidebar link test is split so that placement and ordering fail separately.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The tier was read after the page creation had landed, so a picker change
during that write took the page id from the choice the save started on but
the main-vs-alongside decision from the new one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The dialog spec restubbed location by spreading the already-stubbed one and
never unstubbed it, so an href written by one test stood in for the next and
a skipped navigation went unnoticed. Each test now starts from an empty href
and the globals are restored afterwards.

The guards that hold the save to the page and tier it started on, that drop
a page read the user has moved off, and that keep page-first mode out of the
edit notices, are now covered, as is the refusal of a page-creation response
that did not report success.

The schema display's permission test drove the ref itself, so it passed
whether or not the component asked; the fake composable now answers from the
right the test grants.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
malberts and others added 4 commits September 9, 2026 11:38
Every entry point that creates a Subject now says "Create": the page tool
reads "Create subject here" and the Data tab's button "Create subject",
matching the sidebar link and the Schema page's button. "Add" and "Create"
side by side suggested two different operations.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Beside the edit pencil the "Create <Schema>" link read as another header
control. Below the description it reads as the call to action it is, so it
also takes the progressive primary weight.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
On a Schema page the sidebar's "Create subject" link now reads "Create
<Schema>" and points at Special:CreateSubject with that Schema pinned,
matching the button in the page header.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The call to action on the Schema page is that page's entry point; the sidebar keeps the general
"Create subject" link it shows everywhere else.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate creating a page and its Main Subject in one step

1 participant