Reference → Posts — Reference

Posts — Reference

The Posts surface is the blog engine — and, less obviously, the shared write layer for every long-form record on the platform. It owns blog post records, post categories, post tags, post-type taxonomies, content import / export, the per-post revision system, and the duplicate / soft-delete / restore lifecycle that Pages, Events, and custom content types all reuse.

This page is a reference for platform engineers and integrators. Customer-facing walkthroughs for writing and publishing blog posts live in the customer docs set; this page describes the surface, not the editorial flow.


Overview

Posts live under the Blog module in SG-Admin (the user-facing label is "Blog"; the underlying record type is post). The module renders the standard list / create / edit / history views and exposes a settings panel for blog-wide behavior — default category, posts-per-page on the archive, RSS feed visibility, social-card defaults.

The Posts surface is dual-role. Externally, it is the blog. Internally, it is the post-record action layer — the engine that every long-form content type on the platform reuses for its write operations. Pages, Events, custom objects, and the Blog itself all route their saves, duplicates, deletes, and restores through this layer. When you read the SG-Admin source, the actions file for posts is one of the largest in the codebase; that size is because it serves four content types, not blog posts.

Where it lives in SG-Admin:

  • Sidebar: SG-Admin → Blog
  • URL prefix: /sg-admin/blog/
  • View templates: application/views/Admin/Blogs/
  • Shared write surface: this module's action layer (also used by Pages, Events, Custom Objects)
Two write paths. The action layer exposes two save shapes — a classic editor save (HTML body, excerpt, featured image, taxonomies) and an SG-Builder save (serialized component tree, plus the classic fields). A given post record can carry either shape; the front-end renderer picks the path based on the record's flag.
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Blog [+ New post] │├──────────────────────────────────────────────────────────────────────┤│ Title Categories Status Posted ││ ───────────────────────────── ───────────── ────────── ────────││ Five lessons from migration Engineering published 3d ago ││ Q1 platform recap Highlights published 8d ago ││ How we handle revision histo… Engineering draft 1d ago ││ Spring sale postmortem Highlights, Ops scheduled in 2d ││ Old launch announcement News trash 30d ago ││ ││ [⋯ Edit] [⋯ Duplicate] [⋯ Categories] [⋯ Tags] [⋯ Delete] │└──────────────────────────────────────────────────────────────────────┘

Actions

The Posts surface exposes the following operations.

List and search

Returns the post records, paginated, with title, author, categories, tags, status, and publication-date columns. Supports column sort, multi-faceted filter (status, category, tag, author, date range), and per-page count.

Create post

Opens an empty editor. Required: title. Optional and common: slug, body (classic HTML or SG-Builder canvas), excerpt, featured image, categories, tags, publication state, scheduled-publish date, SEO meta, and social-card overrides. On submit, the record persists in draft status by default.

Edit post

Loads an existing record into the editor. Submit replaces the stored state with the posted values. The editor remembers which write path the record uses — opening a Builder-authored post loads the Builder canvas, opening a classic post loads the rich-text editor.

Save and publish

Two-step publication, identical in shape to the Pages surface. Save persists the draft; Publish moves the record to published and stamps published_at. Schedule sets a future published_at and leaves the status as scheduled until the cron worker promotes it.

Duplicate

Creates a new post record with the same content, a copy-suffix in the title, a unique slug, and status: draft. Taxonomies (categories, tags) carry over; the duplicate is otherwise independent.

Soft delete

Marks the record as trash. Trashed posts disappear from the default list, the archive, the RSS feed, and any cross-referenced widget — immediately.

Restore

Returns a trashed post to its prior status. Slug uniqueness is rechecked; collision returns a structured rejection.

Permanent delete

Hard-removes a trashed record. Irreversible.

Per-post revision history

Same shape as the Pages revision system. Every save writes a revision row. The history view lists revisions in reverse-chronological order. Restore revision loads a historic snapshot back into the live record as a new save.

Manage categories

Categories live in a separate taxonomy table. The category panel exposes list, create, edit, delete, and merge operations. A post can belong to many categories; setting a category to "default" means new posts pick it up automatically.

Manage tags

Tags are a flat, non-hierarchical taxonomy. Same panel shape as categories — list, create, edit, delete. Tag creation can happen inline from the post editor (typing a new tag creates the row on save).

Manage custom taxonomies

Beyond the built-in Categories and Tags, the surface supports operator-defined taxonomies — for example, a "Region" taxonomy on news posts or an "Industry" taxonomy on case studies. Each custom taxonomy is itself a record (name, slug, hierarchy mode) with its own term list.

Set homepage post

A blog-specific homepage flag — pins a post to the top of the blog archive. Distinct from the site-wide homepage role (which is a Pages concern).

Update post configuration

Writes the blog-wide settings: default category, posts-per-page, archive layout, RSS feed visibility, social-card defaults, post-type slug.

Export posts

Produces a bundle of post records (and their taxonomies, revisions, and media references) suitable for re-import into another SGEN site.

Import posts

Bulk-loads posts from an exported bundle. Validates structure, resolves taxonomy collisions (merge or rename), and reports per-record success or skip.


Data model

A post record carries the following fields.

FieldTypeNotes
idintegerPrimary key. Stable across edits.
typeenumpost, page, event, or a custom-object slug. The action layer keys on this.
titlestringDisplay title.
slugstringURL segment. Unique across post records.
statusenumdraft, published, scheduled, trash.
bodytextClassic-editor HTML. Sanitized on save.
canvas_stateJSONSerialized SG-Builder component tree. Used when the Builder write path saved.
write_pathenumclassic or builder. Determines render.
excerptstringOptional. Used in archive cards and RSS.
featured_image_idintegerForeign key to a Media record.
categoriesarrayMany-to-many to the category taxonomy.
tagsarrayMany-to-many to the tag taxonomy.
custom_taxonomiesobjectMap of taxonomy slug → term array.
seo_metaJSONTitle, description, canonical, OpenGraph, schema.
social_cardJSONPer-post override of the default social card.
author_idintegerForeign key to Users.
published_attimestampSet on publish, drives archive sort.
created_attimestampImmutable.
updated_attimestampTouched on save.
Body sanitization. Classic-editor body content passes through a sanitizer on save. The sanitizer strips