Build a Content Element | PagibleAI Documentation

Define the editor contract

A content element starts with a schema entry. The schema names the element, groups its fields, and tells the admin which input control to show. Keep the stored data about meaning rather than layout whenever possible.

The example below defines a release note with a title, summary, release date, and optional link. It is narrow enough for an editor to complete correctly and stable enough for several frontends to consume.

{
  "release-note": {
    "label": "Release note",
    "fields": {
      "title": {"type": "string", "required": true},
      "summary": {"type": "markdown", "required": true},
      "released": {"type": "date", "required": true},
      "url": {"type": "url"}
    }
  }
}

Render the published data

<article class="release-note">
  <time datetime="{{ cms($page, 'data.released') }}">
    {{ cms($page, 'data.released') }}
  </time>
  <h2>{{ cms($page, 'data.title') }}</h2>
  <div>{!! cmsmarkdown(cms($page, 'data.summary')) !!}</div>
</article>

Review before adding fields

Question
Prefer
Avoid
Does the field describe meaning?
released, summary, author
leftColumn, blueText
Can an editor choose correctly?
A short list of valid options
An unexplained free-form code
Will clients reuse it?
A stable value and explicit type
Markup tied to one template
Is it actually required?
Required only when rendering depends on it
Mandatory fields added for completeness