Static CMS
Star StaticJsCMS/static-cms on GitHub
v4.3.0DocsExamplesDemoCommunity

Creating Custom Previews

Static CMS exposes a window.CMS global object that you can use to register custom previews for an entire collection (or file within a file collection) via registerPreviewTemplate (editor view) and registerPreviewCard / registerFieldPreview (collection view).

React Components Inline

registerPreviewTemplate, registerPreviewCard and registerFieldPreview require you to provide a React component. If you have a build process in place for your project, it is possible to integrate with this build process.

However, although possible, it may be cumbersome or even impractical to add a React build phase. For this reason, Static CMS exposes some constructs globally to allow you to create components inline: h (alias for React.createElement) as well some basic hooks (useState, useMemo, useEffect, useCallback).

Editor Preview

registerPreviewTemplate allows you to create a template that overrides the entire editor preview for a given collection.

Params

ParamTypeDescription
namestringThe name of the collection (or file for file collections) which this preview component will be used for
  • Folder collections: Use the name of the collection
  • File collections: Use the name of the file
react_componentReact Function ComponentA React functional component that renders the collection data.

The following parameters will be passed to your react_component during render:

ParamTypeDescription
entryobjectObject with a data field that contains the current value of all widgets in the editor
collectionobjectCollection configuration
fieldsobjectThe fields for the given collection
documentDocumentThe document object the preview is within. If rendered with a frame, it will be the frame's document
windowWindowThe window object the preview is within. If rendered with a frame, it will be the frame's window
widgetForFunctionGiven a field name, returns the rendered preview of that field's widget and value
widgetsForFunctionGiven a field name, returns the rendered previews of that field's nested child widgets and values

Example

const PostPreview = ({ widgetFor, entry, collection, fields }) => {
  const imageField = useMemo(() => fields.find(field => field.name === 'image'), [fields]);
  const imageUrl = useMediaAsset(entry.data.image, collection, imageField, entry);

  return h(
    'div',
    {},
    h('h1', {}, entry.data.title),
    h('img', { src: imageUrl }),
    h('div', { className: 'text' }, widgetFor('body')),
  );
};

CMS.registerPreviewTemplate('posts', PostPreview);

Lists and Objects

The API for accessing the individual fields of list- and object-type entries is similar to the API for accessing fields in standard entries, but there are a few key differences. Access to these nested fields is facilitated through the widgetsFor function, which is passed to the preview template component during render.

List Template Example

For list fields, the widgetFor function returns an array of objects that you can map over in your template. If your field is a list of authors containing two entries, with fields name and description, the return value of widgetsFor would look like this:

[{
  data: { title: 'Mathias', description: 'Co-Founder'},
  widgets: { title: <WidgetComponent>, description: <WidgetComponent>}
},
{
  data: { title: 'Chris', description: 'Co-Founder'},
  widgets: { title: <WidgetComponent>, description: <WidgetComponent>}
}]
const AuthorsPreview = ({ widgetsFor }) => {
  return h(
    'div',
    {},

    // This is a static header that would only be rendered once for the entire list
    h('h1', {}, 'Authors'),

    // Here we provide a simple mapping function that will be applied to each
    // object in the array of authors
    widgetsFor('authors').map(function (author, index) {
      return h(
        'div',
        { key: index },
        h('hr', {}),
        h('strong', {}, author.data.name),
        author.widgets.description,
      );
    }),
  );
};

CMS.registerPreviewTemplate('authors', AuthorsPreview);
Object Example

Object fields are simpler than lists - instead of widgetsFor returning an array of objects, it returns a single object. Accessing the shape of that object is the same as the shape of objects returned for list fields:

{
  data: { front_limit: 0, author: 'Chris' },
  widgets: { front_limit: <WidgetComponent>, author: <WidgetComponent>}
}
const GeneralPreview = ({ entry, widgetsFor }) => {
  const title = entry.data.site_title;
  const posts = entry.data.posts;

  return h(
    'div',
    {},
    h('h1', {}, title),
    h(
      'dl',
      {},
      h('dt', {}, 'Posts on Frontpage'),
      h('dd', {}, widgetsFor('posts').widgets.front_limit || 0),

      h('dt', {}, 'Default Author'),
      h('dd', {}, widgetsFor('posts').data.author || 'None'),
    ),
  );
};

CMS.registerPreviewTemplate('general', GeneralPreview);

Editor Preview Styles

Register a custom stylesheet to use on the preview pane.

CMS.registerPreviewStyle(url);

Raw Styles

If you want to provide a raw CSS string instead of a url, you can pass { raw: true } as the second parameter.

CMS.registerPreviewStyle('.main { color: blue; border: 1px solid gree; }', { raw: true });

Collection Card Preview

registerPreviewCard allows you to create a card template that overrides the cards displayed in the collection view.

Params

ParamTypeDescription
namestringThe name of the collection (or file for file collections) which this preview component will be used for
  • Folder collections: Use the name of the collection
  • File collections: Use the name of the file
componentReact Function ComponentA React functional component that renders a preview card for a given entry in your collection
getHeightfunctionA function that returns the height for your cards. An object containing the current collection and entry are passed into the function at render. If no getHeight function is provided, the height will be 204 if the collection has an image field or 64 if the collection does not have an image field

The following parameters will be passed to your react_component during render:

ParamTypeDescription
entryobjectObject with a data field that contains the current value of all widgets in the editor
widgetForFunctionGiven a field name, returns the rendered preview of that field's widget and value
widgetsForFunctionGiven a field name, returns the rendered previews of that field's nested child widgets and values
hasLocalBackupbooleanWhether the current entry has a local backup

Example

const PostPreviewCard = ({ entry, widgetFor }) => {
  return h(
    'div',
    { style: { width: '100%' } },
    widgetFor('image'),
    h(
      'div',
      { style: { padding: '16px', width: '100%' } },
      h(
        'div',
        {
          style: {
            display: 'flex',
            width: '100%',
            justifyContent: 'space-between',
            alignItems: 'start',
          },
        },
        h(
          'div',
          {
            style: {
              display: 'flex',
              flexDirection: 'column',
              alignItems: 'baseline',
              gap: '8px',
            },
          },
          h('strong', { style: { fontSize: '24px' } }, entry.data.title),
          h('span', { style: { fontSize: '16px' } }, entry.data.date),
        ),
        h(
          'div',
          {
            style: {
              backgroundColor: entry.data.draft === true ? 'blue' : 'green',
              color: 'white',
              border: 'none',
              padding: '4px 8px',
              textAlign: 'center',
              textDecoration: 'none',
              display: 'inline-block',
              cursor: 'pointer',
              borderRadius: '4px',
            },
          },
          entry.data.draft === true ? 'Draft' : 'Published',
        ),
      ),
    ),
  );
};

CMS.registerPreviewCard('posts', PostPreviewCard, () => 240);
Grid View

Post Preview Card Grid View

Collection Field Preview

registerFieldPreview allows you to create a custom preview for a specific field in the table view for collections.

Params

ParamTypeDescription
collectionNamestringThe name of the collection (or file for file collections) which this preview component will be used for
  • Folder collections: Use the name of the collection
  • File collections: Use the name of the file
fieldNamestringThe name of the field
componentReact Function ComponentA React functional component that renders a preview of the field for a given entry in your collection

The following parameters will be passed to your component during render:

ParamTypeDescription
collectionobjectCollection configuration
fieldobjectField configuration
valueFunctionThe current value of the field for the given entry

Example

const PostDraftFieldPreview = ({ value }) => {
  return h(
    'div',
    {
      style: {
        backgroundColor: value === true ? 'rgb(37 99 235)' : 'rgb(22 163 74)',
        color: 'white',
        border: 'none',
        padding: '2px 6px',
        textAlign: 'center',
        textDecoration: 'none',
        display: 'inline-block',
        cursor: 'pointer',
        borderRadius: '4px',
        fontSize: '14px',
      },
    },
    value === true ? 'Draft' : 'Published',
  );
};

CMS.registerFieldPreview('posts', 'draft', PostDraftFieldPreview);
Table View

Post Draft Field Preview Table View