UI Extensions

Introduction

The Contentful Web App uses components (called appearances) to make the fields of a content type editable. UI Extensions are enabling developers to replace these components with HTML5 applications so the editing experiences of the Contentful Web App can be customized.

Technically speaking a UI Extension lives in a sandboxed <iframe> which interacts with the Contentful Web App through the UI Extensions SDK. This SDK is a proxy to the Content Management API and is acting on behalf of the logged-in user. The code of the UI Extension is fully custom and can either be uploaded to Contentful or be self-hosted.

A short text field using a built-in appearance

The image below shows a field title of type short text using the default single line appearance:

A short text field using a custom UI Extension

The image below shows the same field rendered with a UI Extension. The field now renders a diff of the published and draft field value:

The diff UI Extension uses the UI Extensions SDK to retrieve the published field value. Using the jsdiff libary it computes and renders a visual diff of the two values as feedback for an author.

Vanilla HTML5 UI Extension template

As mentioned, UI Extensions essentially are small HTML5 applications. That means there are many ways to implement them – from basic HTML and JavaScript to richer apps based on frameworks such as React, Angular or Vue. It all depends on the individual use case the UI Extension is supposed to solve.

We prepared a vanilla HTML5 UI Extension template implementing the basic lifecycle methods to better understand the concept.

The template renders in the Contentful Web App like this:

The template includes:

  • the UI Extensions SDK library
  • a Contentful look-and-feel by loading our CSS library
  • basic handling of user-generated events (here: keyboard input)
  • basic handling of externally generated events (here: changes introduced by other authors)
  • cleanup of event listeners

template-vanilla.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <!-- UI Extensions CSS -->
  <link rel="stylesheet" href="https://contentful.github.io/ui-extensions-sdk/cf-extension.css">
  <!-- UI Extensions SDK -->
  <script src="https://unpkg.com/contentful-ui-extensions-sdk@3"></script>
</head>
<body>
  <!-- Custom markup of the UI Extension -->
  <div class="cf-form-field">
    <input type="text" class="cf-form-input">
    <div class="cf-form-hint">I am a UI Extension.</div>
    <div class="cf-form-hint">Instance params: <span class="instance-param-value"></span></div>
    <div class="cf-form-hint">Installation params: <span class="installation-param-value"></span></div>
  </div>

  <!-- Custom logic of the UI Extension -->
  <script>
    'use strict';

    // When UI Extensions SDK is loaded the callback will be executed.
    window.contentfulExtension.init(initExtension);

    function initExtension (extensionsApi) {
      // "extensionsApi" is providing an interface documented here:
      // https://github.com/contentful/ui-extensions-sdk/blob/master/docs/ui-extensions-sdk-frontend.md

      // Automatically adjust UI Extension size in the Web App.
      extensionsApi.window.startAutoResizer();

      var inputEl = document.querySelector('.cf-form-input');

      //  The field this UI Extension is assigned to.
      var field = extensionsApi.field;

      document.querySelector('.instance-param-value').appendChild(document.createTextNode(extensionsApi.parameters.instance.exampleParameter))
      document.querySelector('.installation-param-value').appendChild(document.createTextNode(extensionsApi.parameters.installation.exampleParameter))


      // Callback for changes of the field value.
      var detachValueChangeHandler = field.onValueChanged(valueChangeHandler);
      // Handle keyboard input.
      inputEl.addEventListener('input', keyboardInputHandler);
      // Handle DOM "onbeforeunload" event.
      window.addEventListener('onbeforeunload', unloadHandler);

      // Handler for external field value changes (e.g. when multiple authors are working on the same entry).
      function valueChangeHandler (value) {
        inputEl.value = value || '';
      }

      // Event handler for keyboard input.
      function keyboardInputHandler () {
        var value = inputEl.value;
        if (typeof value !== 'string' || value === '') {
          field.removeValue();
        } else {
          field.setValue(value);
        }
      }

      // Event handler for window unload.
      function unloadHandler () {
        window.removeEventListener('onbeforeunload', unloadHandler);
        inputEl.removeEventListener('input', keyboardInputHandler);
        detachValueChangeHandler();
      }
    }
  </script>
</body>
</html>

Installing UI Extensions into a space

There are two ways to install UI Extensions into a space. You can use the Content Management API (CMA) via our CLI or you could install directly from the Contentful web app.

Installing from the Contentful web app

Navigate to Space settings > Extensions in the Contentful web app to view, create, update or install an example.

Go to the Web App to manage your UI Extensions

Within the extensions view, you have multiple options:

Add a new extension

This dialog allows you to create an extension from scratch. You need to specify a name, field types and the inline code editor allows you to modify the source code of the extension. For guidance, refer to the Vanilla template from the section above.

Install an example

We are providing a curated list of example that you easily install and use in your own space. These examples can be customized to your specific needs.

Install from GitHub

We support fetching UI Extensions from public GitHub repos. Provide a valid link to an extension.json file (either to the raw file or just a file on GitHub).

Important: if you use Contentful to host your UI Extension by using the srcdoc property, it's necessary to commit the html bundle into the same repository for the import process to work.

Extensions are installed to a Contentful space through the Content Management API /spaces/:spaceId/extensions endpoint. To make it more convenient we added support for extensions to the Contentful CLI.

Installing with the Contentful CLI

Prerequisites

  • Install the Contentful CLI so the contentful command is available
  • Make sure you have an account at Contentful with admin access to a space

Step 1: Prepare the code of a UI Extension

Create an HTML file to hold the code for the UI Extension. To get started we recommend to use the template-vanilla.html we introduced in the section above.

Step 2: Install into a space

Install the UI Extension into a Contentful space using the Contentful CLI:

contentful extension create \
  --name "My UI Extension" \
  --field-types "Symbol,Text" \
  --srcdoc template-vanilla.html

For a full reference read the managing extensions guide.

Assigning UI Extensions to a field

The last step is to assign the extension to a field of a content type. The steps are:

  1. create a Content Type
  2. create a field in the Content Type
  3. head to Settings > Appearance of the field
  4. select the UI Extension your created
  5. create an entry of your Content Type to see your UI Extension in action

The image below shows the Appearance tab under Setting of a field: