Pages — Reference
The Pages surface is where the static structure of a site lives — the home page, about, contact, landing pages, every routable URL that isn't a blog post, event, product, or other content-type record. It owns the URL slug, the layout, the SG-Builder canvas state, the publication state, the SEO meta, and the per-post revision history.
This page is a reference for platform engineers and integrators. Customer-facing walkthroughs for adding, editing, and publishing pages live in the customer docs set; this page describes the surface, not the workflow.
Overview
Pages live under the Pages module in SG-Admin. The module renders three primary views — the page list, the create / edit form, and the per-page revision history — and shares its write surface with the broader post-record system. The shared write surface is important: many of the operations described below (duplicate, soft-delete, restore, revision-restore, set-homepage, import) are implemented once at the post-record layer and reused by Pages, Blog posts, Events, and custom content types.
When you read the SG-Admin source, you will see the Pages module file is intentionally thin — most of the heavy work lives in the shared post-actions surface. Integrators should think of Pages as "the post-record surface filtered to records of type page" rather than as a separate engine.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Pages
- URL prefix:
/sg-admin/pages/ - View templates:
application/views/Admin/Pages/ - Shared write surface: the post-record action layer (also used by Blog, Events, Custom Objects)
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Pages [+ Add new] │├──────────────────────────────────────────────────────────────────────┤│ Title Slug Status Homepage Updated ││ ────────────── ────────────────── ────────── ──────── ─────────││ Home home published ★ 2d ago ││ About about published — 5d ago ││ Pricing pricing published — 1d ago ││ Contact contact draft — now││ Legacy Landing legacy/spring-26 archived — 44d ago ││ ││ [⋯ Edit] [⋯ Duplicate] [⋯ Set as homepage] [⋯ Delete] │└──────────────────────────────────────────────────────────────────────┘Actions
The Pages surface exposes the following operations. Some are implemented directly on the Pages module; most route into the shared post-record action layer.
List and search
Returns the page records, paginated, with title, slug, status, homepage flag, author, and updated-at columns. Supports column sort, free-text filter, and per-page count. The page list is the post-record list filtered to type page.
Create page
Opens an empty editor. Required: title and slug (slug auto-derives from title but stays editable until first save). Optional: layout template, parent page (for hierarchical URLs), SEO meta, visibility, and the SG-Builder canvas state. On submit, the record persists in draft status by default.
Edit page
Loads an existing record into the same editor used for create. Submit replaces the stored state with the posted values. The editor preserves the SG-Builder canvas as a serialized component tree on the record — opening the editor a second time deserializes that tree into the canvas.
Save and publish
Two-step publication. Save persists the draft; Publish moves the record into the published state and assigns it a publication timestamp. Republishing an already-published record updates the timestamp. The two operations are deliberately split so an operator can stage many edits before they go live.
Duplicate
Creates a new page record with the same content, a copy-suffix in the title, and a unique slug. The duplicate starts in draft status regardless of the source's status. The duplicate carries its own record identifier — relationships pointing to the source page do not transfer.
Set as homepage
Marks the page as the site's homepage. Exactly one page holds this role at any time; setting it on a new page clears it on the previous one. The homepage role affects URL resolution — the homepage's canonical URL is /, not /.
Engineering note. When a page becomes the homepage, the front-end sheds the body class derived from the slug. CSS scoped tobody.page-stops applying. Scope custom CSS tobody.page_id-(the numeric record identifier) for rules that should survive a homepage flip.
Soft delete
Marks the record as trash. Soft-deleted pages disappear from the default list but remain queryable via the trash filter. URL resolution stops serving the page immediately.
Restore
Returns a trashed page to its prior status (draft or published). The slug is preserved; if a new page has been created at the same slug in the meantime, restore returns a structured rejection with the conflicting slug named.
Permanent delete
Hard-removes a trashed record. Irreversible. Author attribution on associated revisions is preserved, but the revisions themselves are removed.
Per-page revision history
Every save writes a revision row. The history view lists revisions for a given page in reverse-chronological order with the saving operator, the timestamp, and a short diff summary. Restore revision loads the historic canvas state back into the live record as a new save — the restored state immediately becomes the current draft, with the prior live state preserved as another revision.
Import
Bulk-loads pages from an exported bundle (typically from another SGEN site). Import accepts the bundle file, validates structure and slug collisions, and reports per-record success or skip. The shape and import path are shared with Templates and Posts.
Data model
A page record carries the following fields.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
type | enum | Always page for records managed by this surface. |
title | string | Display title. Used in admin lists and as the default tag. |
slug | string | URL segment. Unique across pages and posts. |
parent_id | integer | Optional. Enables hierarchical URLs (/parent/child). |
status | enum | draft, published, scheduled, trash. |
is_homepage | boolean | True on exactly one page at a time. |
layout_template | string | Theme template slug. Falls back to default. |
canvas_state | JSON | Serialized SG-Builder component tree. Empty for non-Builder pages. |
seo_meta | JSON | Title override, description, canonical, OpenGraph, schema. |
author_id | integer | Owning user. Foreign key to the Users surface. |
published_at | timestamp | Set on first publish, updated on republish. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any save. |
Homepage uniqueness. is_homepage = true is exclusive — a database constraint, not a convention. The set-as-homepage action handles the swap atomically.
Revision storage. Revisions live in a separate table, one row per save, carrying the full canvas state at that point. Storage cost grows with edit cadence; the Settings module exposes a retention cap (default 25 per page, configurable).
SAVE ┌─────────────────────┐edit canvas ──► │ page record (live) ││ status: draft │└──────────┬──────────┘│▼┌─────────────────────┐│ revision row │ ← one per save│ snapshot of canvas │ ← FIFO trimmed at retention cap└─────────────────────┘RESTORE REVISIONhistoric row ──► becomes new current draftprior current ──► becomes another revisionPermissions
Access to the Pages surface is gated at the standard admin layer, plus per-action capability checks.
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List pages | ✔ | ✔ | ✔ |
| Create page | ✔ | ✔ | — |
| Edit any page | ✔ | ✔ | — |
| Publish | ✔ | ✔ | — |
| Set as homepage | ✔ | — | — |
| Duplicate | ✔ | ✔ | — |
| Soft delete | ✔ | ✔ | — |
| Restore | ✔ | ✔ | — |
| Permanent delete | ✔ | — | — |
| View revision history | ✔ | ✔ | ✔ |
| Restore revision | ✔ | ✔ | — |
| Import bundle | ✔ | — | — |
Audit. Every save, publish, delete, restore, revision restore, homepage swap, and import emits an Activity Log entry with the acting operator and the target record.
SAVE / PUBLISH / DELETE│▼┌─────────────────────────────┐│ Admin gate │ unauth → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Per-action capability check │ role lacks cap → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Authorship gating (if set) │ not own + "own only" mode → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Slug / homepage uniqueness │ collision → structured rejection└──────────────┬──────────────┘▼action executes│▼Activity Log entryRelated references
- Posts — Reference. Shares the post-record action layer with Pages. Most of the write operations described above are implemented there.
- Templates — Reference. Layout templates referenced by
layout_templatelive under Templates. Changes propagate to every page using the template. - Users — Reference. Author attribution and the per-action capability checks resolve against the Users module.
- SEO — Reference. The
seo_metaJSON shape is defined and validated under the SEO module. - Settings — Reference. Revision retention cap, fallback layout, and slug-rewrite rules live in Settings.
- Media — Reference. Canvas-embedded image references resolve against the Media library.
/docs/pages.