Measurable Success «10 Checkpoints for Future-Proof Enterprise CMS» White Paper
Measurable Success - White Paper

Scrivito’s Data Model

Scrivito’s Data Model

With Scrivito, all editable content is stored in CMS objects. Such objects contain the data of pages or images, for example, and are the only entities that are stored and retrieved individually, together with the widgets they may include.

Let’s take a look at a simple page and try to identify its components, the widgets. We’ll ignore the layout elements (outside the boxed area on the screenshot below) since most of them are related to the application and include only small portions of content used for rendering navigations, for instance.

  • Like every page, this one, too, is represented by a single CMS object. CMS objects are stored in a database in which each of them occupies exactly one entry.

  • The headline, the text block, and the image are widgets. They’re not CMS objects but contained in an attribute of the CMS object. However:

  • The image is contained in an image widget but is a CMS object of its own. If you were to delete the widget or the page containing it, the image itself would remain in the CMS because the widget just references it (see below for details).

What's in a CMS object?

All CMS objects are based on a model that defines their properties. In Scrivito’s terminology, a page model is called object class, and properties are attributes. The object class for simple pages like the one above could look like this:

Scrivito.provideObjClass('Page', {
  attributes: {
    title: "string",
    body: "widgetlist",
  }
});

The flexibility and usefulness of this object class for the editor is based on the body attribute, a widgetlist. All the widgets an editor places on such a page are added to this attribute. Next to widgetlist, various attribute types for maintaining different kinds of content exist.

In addition to such an object class, we merely require a component that renders its instances, i.e. the actual pages, which comes down to rendering their respective body attribute, like so:

Scrivito.provideComponent("Page", ({ page }) => (
  <Scrivito.ContentTag tag="div" content={page} attribute="body" />
));

Widgets have attributes, too

You’ve probably seen widgets in action already. As an editor you can choose them from the various kinds of widgets available in your project. As indicated above, placing one onto a page means adding it to a widgetlist attribute.

The kind of content widgets of a specific type should be able to contain can be defined by providing a model, analogously to CMS object classes:

Scrivito.provideWidgetClass('HeadlineWidget', {
  attributes: {
    headline: "string",
    level: ["enum", {values: ["h1", "h2", "h3", "h4", "h5", "h6"]}],
  }
});

As you can see, the widget model above includes two attributes, headline and level. Note that you can add widgetlist attributes to widget models, too. The ability to nest widgets makes it possible to let editors structure content in a more refined way using column or section widgets, for example.

Behind the scenes: storage

As indicated, Scrivito stores all CMS objects in a database, keeping track of their attributes. The example page above is represented as a data structure similar to the one you can see here. An attribute of the widgetlist type, here body, is an array whose elements represent the widgets it contains.

The attributes given to objects via their object class are custom attributes. However, every CMS object also has a built-in set of system attributes, e.g. id for identifying them, or _path for maintaining the tree-like hierarchy objects may be part of. The data Scrivito stores for a CMS object includes both kinds of attributes.

As pointed out above, images are handled as individual CMS objects that are referenced wherever they are needed. Thus, the value of the image attribute of the ImageWidget is an ID referencing the image object in the CMS.

{
  id: "b7db5bde279ce347",
  _path: "/articles/b7db5bde279ce347",
  _objClass: "ArticlePage",
  title: "On something relevant",
  body: [
    {
      id: "be4d9ac4",
      _objClass: "HeadlineWidget",
      headline: "Headline",
    },
    {
      id: "76c2af09",
      _objClass: "TextWidget",
      body: "Eu quis ullamco cillum…",
    },
    {
      id: "d1f794dd",
      _objClass: "ImageWidget",
      image: "82d466cf4a9df6e1",
    },
  ],
}

Binaries are special

Scrivito identifies binary content such as images, videos, PDF files, etc. through attributes of the binary type in CMS objects. Let’s take a look at the typical definition of an Image object model.

The attribute name used here is blob, Scrivito’s default name for accessing the binary, e.g. for rendering.

Scrivito.provideObjClass('Image', {
  attributes: {
    blob: "binary",
    caption: "html",
  }
});

When uploading a binary file to an Image object, Scrivito transfers it to Amazon’s S3 file storage and places its URL in the blob attribute of the CMS object. All this is done transparently in the background; nobody needs to clear away image files after the widgets or CMS objects referencing them have been deleted.

A word on indexing for searching

Scrivito maintains search indexes for the published content as well as for each working copy. All the attributes of a CMS object, e.g. a page like the one above, including the attributes of the widgets it contains, are indexed and associated with that specific object. So, one CMS object not only corresponds to exactly one entry in the database but also to exactly one entry in the search index.

Summarized, ...

CMS objects and all their textual content including their metadata are stored in a database. Binary data is persisted using file storage services and linked to objects in the database. Scrivito maintains search indexes for all the content in all working copies.