Technology

Simple website approach using a Headless CMS: Part 2

The focus of this post is on Cockpit CMS, because it's a pure Headless CMS that is open-source, simple, with a great UI and provides the basis for starting a Headless website.

Appnovation logo
Appnovation

Using Cockpit CMS

In my previous post, I presented some Headless CMS solutions and suggested using Drupal mostly due to the content editorial capabilities and flexibility. Drupal can be leveraged as a vanilla solution or in a distro flavour (e.g. Contenta, Reservoir). I also approached Cockpit CMS, because it's a pure Headless CMS that is open-source, simple, with a great UI and provides the basis for starting a Headless website.

So the purpose of this post is to give you an overview of Cockpit, in terms of installation, configuration,  the core concepts and how to retrieve contents. In my next post of that series, I'll provide the last piece in form of a simple website implemented in React and that can consume dynamically the contents available on Cockpit.

 

Cockpit CMS

Cockpit comes in two flavours, Official Release, the most stable or Preview, also known as Next. All examples I am providing here are based on the Next branch.

 

Requirements

  • PHP >= 7.1

  • PDO (SQLite Support or MongoDB)

  • GD and ZIP extensions

  • Nginx or Apache

Humm! Quite simple, right? Yes, as you can see, no generation or build scripts, or heavyweight PHP libraries or dependencies. It means that Cockpit can run with low resources.

 

Installation

The installation is a straightforward process, just extract to your docroot folder and point the browser to http://<yourdomain>/install, no configurations are required during the installation, you are redirected to the login page and can login using admin/admin (better to change the password after the first login).

A docker compose file is also provided, so if you want to try the docker version just run:

docker-compose up -d

 

Usage and Core concepts

Cockpit is based on the below main concepts:

  • Collections

  • Regions

  • Forms

  • API

  • Webhooks

  • Collections

  • Addons

 

Collections

Collections are probably the most important, they can be compared with content types on Drupal, a collection can define any piece of information (e.g. Page, a Product, etc..) so as a node in Drupal, a collection contains fields. Cockpit provides already a complete set of field types:

Asset, Boolean, Code, Color, Color Tag, Date, File, Gallery, HTML, image, Layout, Layout Grid, Location, Markdown, Multiple Select, Object, Password, Rating, Repeater, Select, Set, Tags, Text, Textarea, Time, wysiwyg (html editor), Collection Link

Above list is probably more than enough for most of the business cases to define a content type, however, if you require something different you can extend them by providing your own field types.

Something that can seem a bit weird is that the definition of the field attributes is a plain JSON object! Yes, it is, however, I don't see it as a big problem, in fact for me it worked better I was able to define all the attributes of a field quicker than using a step based UI. Something that helps is to have the docs in hand (https://getcockpit.com/documentation/reference/fieldtypes), so you can copy paste the JSON object directly from the template and do the modifications you need.

http://take.ms/MEStO


Defining the fields as JSON objects is something that I consider valuable, as it permits to update the fields easily if required.

Resuming, collections are the core of Cockpit in terms of structuring information, they can virtually represent any piece of information and Cockpit interface is powerful enough for developers and simple enough for non-technical users, the perfect wedding.

I will return further below in the article to collections as I pretend to demonstrate it's power by providing some examples.

 

Regions

Regions are editable contents and code snippets that can be re-used, for example, if we need a block of content for contacts that will display a list of contacts (e.g. phone number, e-mail, address) we can build a region named Contacts and access it using the API. One major difference to collections is that we can define templates for regions, however, I believe that by doing that we are corrupting the main headless concept, so I suggest to use them without templates.

 

Forms

Forms are available on the Next branch, however, they are not yet functional and no documentation is available. They look to seem a kind of special collection to be exposed as typical forms, a bit similar concept of webforms in Drupal.

 

API

The API is the core of the headless CMS, is the bridge between the client (application) and the contents. Cockpit provides a security layer based on API tokens, it's possible to define full access tokens, custom tokens that can interact with specific collections only or can only retrieve and not save data, or tokens that are user based.

Retrieving collections using the API and Javascript can be performed with one command:

fetch('/api/collections/get/basicpage?token=xxtokenxx', {
   method: 'post',
   headers: { 'Content-Type': 'application/json' },
   body: JSON.stringify({
       filter: {published:true},
       limit: 10,
       sort: {_created:-1}
   })
})
.then(res=>res.json())
.then(res => console.log(res));

 

On the above example we are retrieving the last 10 contents of type "basicpage" that have the field published = true.

 

Webhooks

Webhooks are reactive actions that can interact with 3rd party applications/services when something happens (e.g. after or before a collection is saved or a collection is removed). Let's imagine that we have a newsletter collection that collects an email and a name and we want to store that data in a google sheets document. We can create a webhook with a 3rd party service like Zappier (as it can interact easily with Google sheets) that is triggered every time that the subscription collection is saved. When triggered it will invoke the Zappier service with the saved data and Zappier will create a new entry in the configured Google sheet.

 

Addons

Like Drupal or other CMS, Cockpit can be extended by the installation of add-ons, basically, we need to follow a simple structure. An addon is a folder that should contain a bootstrap.php file where depending on the Addon functionality (e.g. It will provide Admin functionality or a REST endpoint) we need to provide the correct code to initialize it.

An addon implementation may require the understanding of Riot.js (http://riotjs.com) if it provides admin functionality and the Lime php micro framework (https://github.com/agentejo/lime) for example to handle events.


After playing a bit with Cockpit I implemented two new add-ons:

 

Conclusion and Next Steps

For me, the most interesting part of Cockpit is not on the features that are available but in the way they are, and mostly on the quickness of creating/updating collections. So taking that into consideration my next step is to build something usable and see how it really works to build a headless experience. To prepare that exercise I will be using React.js in the frontend as a consumer for Cockpit contents.

My simple exercise consists of a typical website that needs to provide:

  1. Creation of Basic Pages using a "componentized" approach, so instead of having a typical bunch of static fields like summary, body, etc, I have instead different components:

  • Banner

  • Text

  • Block of text with a CTA

  • FAQ section

  • Quote section

  • etc..

  1. Have a main menu and the ability to define the pages that should be visible in the main menu

  2. Responsive

  3. Easy to change the UI without touching Cockpit

Using a "Componentized" approach permits easily to have a relationship between the Collection and a React component, for example, if you pick The Quote section it can be described in Cockpit with two fields, one for the quoted text and other for the quote author, for the quoted text we can use a Markdown field and for the author we can use a simple text field. When retrieving the collection it will be represented in JSON as below structure:

[
   {
       "author": "Some Author",
       "name": "Quote - Homepage",
       "content": "Quo usque tandem abutere, Catilina, patientia nostra?",
       "_mby": "5a61396e7640edoc1261186187",
       "_by": "5a61396e7640edoc1261186187",
       "_modified": 1517826090,
       "_created": 1517347771,
       "_id": "5a70e3bb09cdddoc1719074663",
       "_link": "quote"
   }
]

On the client side, we can build a Quote stateless component, that has two props, the quoted text, and the author and finally render the markup. The below workflow represents the build of the component from the Cockpit collection until is rendered on React:

 

Quote diagram

 

Pretty simple right! The same approach is applied to all other components, we have in Cockpit the content structure and in React we build the corresponding component, depending on the functionality of each and interaction with the user the React components can be stateful or stateless.

In my next post  the third and final part of this series, I’ll detail the React implementation, and will provide a full working example in React and Cockpit.

 

***

This blog post was originally posted on Appnovation site on 13 February, 2018, authored by Paulo, Senior Drupal Developer.

Headless solution using Cockpit