Template Developers: Template Sections

A section is a reusable part of a page (a Hero, article list, gallery, or contact form) rendered from one entry in the page's pageItems list. Its presentation must stay compatible with the content the template receives.

Template paths and editor controls depend on the separate template repository. Confirm them in your checkout; see what the product defines.

Separate the CMS data shape from the component's props

The Page schema exposes PageItem.type and a JSON config. It does not constrain config to a particular Hero or gallery schema, so a template must validate that data before treating it as typed component props. On Web Builder pages the same items are WebPageItems carrying contentType/contentTypeId instead of the CMS objectType/objectId; the deployer copies each item into data/pages/*.json under the objectType/objectId key names. See buildPageConfigs.

For example, a template might define these component types:

type HeroConfig = {
  title: string;
  description?: string;
  imageUrl?: string;
  imageAlt?: string;
  primaryCta?: { label: string; href: string };
};

type HeroProps = {
  config: HeroConfig;
};

These names are illustrative template types, not GraphQL fields guaranteed by erxes. At the data boundary, validate unknown configuration using the selected template's established validation approach before passing it to the component. Avoid a broad any type that hides missing or incompatible values.

Preserve registration and identity

Locate the mapping from the item's type to a component, including any separate fixture, preview, and CMS renderers. Common locations include app/page.tsx, lib/renderSections.tsx, and lib/usePage.tsx, but your template may differ.

UI-only scope

For a UI-only assignment, change the existing component's presentation and keep its identifier, inputs, and data hooks intact. Do not rename a pageItems[].type value or alter the fetch that supplies it. For a planned new section, update every supported renderer, editor definition, validator, and fixture together.

Render every state

Support missing optional text, long headings, empty collections, and failed requests. Use the existing asset and route helpers. Give images appropriate alternative text and keep links valid when content is unavailable.

A section that lists linked records (for example, a type that references posts through objectType/objectId or contentType/contentTypeId) needs a loading state, an empty state, and a bounded list. Keep data fetching and secret credentials on the server where required; a section needing browser state can receive a safe, serialized data subset. Follow the CMS rendering examples for integration behavior.

For builder-managed pages, cpWebPage returns the same section list scoped to a webId (see the WebPage schema):

query CpWebPage($slug: String, $webId: String, $language: String) {
  cpWebPage(slug: $slug, webId: $webId, language: $language) {
    _id
    name
    slug
    pageItems {
      _id
      name
      type
      content
      order
      contentType
      contentTypeId
      config
    }
  }
}

Check the section

Use a known fixture, an empty fixture, and representative live content. Check the component in every supported rendering mode and on more than one page if it is shared. Check responsive layout, keyboard controls, image sizing, and loading/error feedback.

Use the designer section catalog to agree on editable fields and states, then continue with Template Pages.

Was this helpful?