The Shipped Screens

The admin shell ships a fixed set of screens, each at a stable URL under /_admin/. This page is the index to all of them; the editor, media, model, and workflow behaviors have their own chapters linked below.

ScreenURLPurpose
Login/_admin/loginToken entry, mints the session cookie
Dashboard/_admin/dashboardRecent edits, validation summary, role notice
Pages list/_admin/pagesPaginated, filterable, sortable table of pages
Pages tree/_admin/pages/treeHierarchical view; large folders lazy-load
Page new/_admin/pages/newCreate-page form with model selection
Page editor/_admin/pages/{path}Edit / Source / Diff modes, live preview, save
Media library/_admin/mediaThumbnail grid with search, type, and folder filters
Media detail/_admin/media/{path}Read-only asset detail drawer
Models/_admin/modelsRead-only list of loaded document models
Model detail/_admin/models/{name}Read-only field definitions for one model
Validation report/_admin/validationSite-wide validation issues with filters
Settings/_admin/settingsToken rotation, build time, license expiry

Dashboard

GET /_admin/dashboard is the landing screen. It shows the 5 most-recently-modified pages and a validation summary bucketed by severity, plus a role-specific notice for the Publisher role. Two HTMX widgets auto-refresh every 30 seconds:

  • Recent edits — GET /_admin/_widgets/recent returns a fragment of the 5 pages sorted by Modified descending.
  • Validation summary — GET /_admin/_widgets/validation-summary returns the severity-bucket fragment with current issue counts.

Pages list

GET /_admin/pages shows a paginated list (default 50 per page, controlled by offset / limit query parameters). It supports:

  • Filters: model, status, tag, and a free-text search over title and URL.
  • Sort: by modified, title, url, date, or status.
  • Order: ascending or descending.

The endpoint serves either a full page or an HTMX tbody fragment, and also handles the POST from the new-page form for create submissions.

Pages tree

GET /_admin/pages/tree renders a hierarchical view of all pages, with the root URL defaulting to /. Nodes with more than 200 children lazy-load their subtree fragments via GET /_admin/pages/tree/_subtree to keep the initial render fast.

Page new

GET /_admin/pages/new renders a single-column create form with a model dropdown (optionally preselected via a model query parameter), a title input, an auto-derived editable path field, a Status selector (Draft / Published, defaulting to Draft), and a read-only Defaults preview YAML block showing the chosen model’s schema defaults. The defaults block is wired to both the model and status dropdowns via GET /_admin/_widgets/defaults-preview, so it reflects the status the page will actually be created with rather than the model’s default. The form is disabled for the Publisher role. See Media and Page Management for the full create flow.

Page editor

GET /_admin/pages/{path} opens the page editor. It has three modes — Edit, Source, and Diff — covered in detail under Page Editing. All fields are disabled for the Publisher role.

Media library

GET /_admin/media displays a paginated thumbnail grid with substring search, a type filter, a folder filter, and pagination. It serves a full page or an HTMX grid fragment, and supports a no-JS fallback via a return_to query parameter. See Media and Page Management.

Media detail

GET /_admin/media/{path} returns a read-only detail drawer for a single asset — dimensions, type, file size, and a used-by list of pages that reference it — shown in the sidebar when a thumbnail is clicked.

Models

GET /_admin/models lists every loaded document model in read-only form. Model editing is a deferred feature; this screen browses the schema only.

Model detail

GET /_admin/models/{name} shows the read-only detail of a single document model, including its field definitions, types, and metadata.

Components

GET /_admin/components lists every component a theme declares, generated from the schema registry: its origin (builtin, theme, or plugin), whether the canonical set fixes the name, how it takes a body, and its attributes. A manifest added to a theme appears here with no second edit. The switcher at the top reads another theme in the theme directory, so two themes declaring one name are two listings, each with its own markup.

GET /_admin/components/{name} shows one component: its description, every attribute with what it holds and whether it is required, the call to insert, and the markup that theme renders for it.

The page editor carries the same set as a Components palette under the body toolbar. Choosing one inserts its call at the caret, with the required attributes stubbed, so what it writes is what accent validate accepts.

Component at the caret

Below the palette, Component at the caret opens the inspector. Put the caret inside a component call, choose Inspect, and the panel shows that component’s attributes as form fields – the same fields the editor uses for frontmatter, built from the types the component’s manifest declares.

Editing a field rewrites only that attribute’s value. Your spacing, your quoting, and the component’s body stay exactly as you wrote them.

A drop-down whose current value is not one of the declared values shows that value as its own selected entry, rather than the first declared one, so the form agrees with the file and with the finding that names the value. The same holds for an enum field in the frontmatter editor whose file holds a retired value.

Anything accent validate says about the component appears above the fields, in the wording the command itself uses, so you read one message rather than two.

If a value does not fit what the attribute holds, the panel says so and leaves the document unchanged, rather than accepting the edit and discarding it. The same happens when the caret has left the component since you chose Inspect, or when the attribute has changed under the panel, and the panel says which it was, so you know whether to retype the value, put the caret back, or read the line beside the attribute.

Some attributes appear without a field, with a line saying why:

  • A value the page resolves when it renders, such as $page.title or a function call. A field would show it empty, and saving would write that emptiness over your reference.
  • A value the syntax implies rather than spells, such as the #id and .class shortcuts.
  • A list or an object. Edit those in the document.
  • A name the component carries twice. Two fields with one name cannot say which one you meant, so both are shown as they are written.

Validation report

GET /_admin/validation displays site-wide validation issues. Filters include severity (error / warning / info), a free-text search over message and URL, and a check-type filter. Severity and search filters are applied locally. The endpoint serves a full page or an HTMX tbody fragment.

Settings

GET /_admin/settings shows the admin shell’s settings: the last token-rotation timestamp, the build time, and the license expiry. POST /_admin/settings/rotate-token rotates the token (see Token rotation).

Color scheme

The admin shell ships light and dark themes. The Color scheme section on the Settings screen offers three choices – Light, Dark, and Match system (the default) – stored per browser in localStorage.

For quick switching there is also a moon/sun toggle in the top bar, visible on every screen. It flips between explicit light and dark; returning to Match system is done from Settings. Both controls share the same stored preference, so a toggle click updates the Settings radios and vice versa.