Recently I’ve been toying around with Contentful. A CMS with a fresh new approach to content management. The CMSs I’ve been working with in the past have been of the “install this package to your solution and build your templates”-variety. For example EPiServer, Joomla, Drupal, SiteCore etc. Contentful instead introduces the idea of managing your content separately in the cloud and accessing it through simple yet powerful REST apis.

Historically if a client would want to build a new website the dialogue might go something like this: “We’ll start by defining the look and feel for a few weeks, then we’ll start building the actual website, then we’ll deploy it to staging and there you can start creating your content which we’ll then copy over to production once ready”.

The problem with this approach is that the producing of content will have to wait as it is dependent on the presentation. This is of course far from ideal and contentful presents an interesting solution to this by moving the production of content into their cloud instead of into a management system tied to the actual website presenting it.

But what is the point, you might ask, of producing content with nowhere to present it yet? There might of course be several good reasons for this but a few that immediately cross my mind are;

  • You might want to postpone the selection of technical platform, but not fall behind in the production of content.
  • You might want to create content for several channels (mobile app, web site etc.), but none of them might be production ready yet.
  • You might want to get started creating content quickly. (Who wouldn’t?)

As just about everyone that has been involved in a CMS-project can witness; The production of content almost always comes too little, too late and presents the application with problems that historically have been very hard to catch during development and testing. By putting the content in the cloud we could use the exact same content in all environments, mitigating the problems of poor test data and making sure our design holds up in a production environment from day one.

While that sounds all fine and dandy, how does it really work?

Imagine we were hired to build a simple web application that needs to be powered by a CMS; it needs a StartPage and ArticlePages, logged in users should be able to like and comment certain pages. We should also be able to categorize pages by tags. All fairly common requirements for any CMS-project today. Let’s compare our process in building such an app in EPiServer (a traditional CMS) and Contentful.

For both systems we’d first have to identify our content types which in our simplified example is rather easy: StartPage, ArticlePage, Like, Comment and Tag are all good candidates. Now here’s where our process would start to diverge. In the EPiServer case we’d start writing code to hardwire our ContentTypes to database models. Something like this:

[ContentType]
public class StartPageContentType : PageData
 {
	public string Heading { get; set; }
 }

In Contentful no code would have yet to be written. We’d simply log into the user interface and start creating our ContentTypes, like so:

startpage

To be fair it is also possible to create content types through the web interface in EPiServer, but to do that we’d have to have the site up and running already… also, nobody does that because it makes it harder to create strongly typed models for your views.

We’d also have to create a couple of properties for our content types. In the EPi case this would correlate to actual C# properties and the EPiServer edit interface would translate this to editable properties. In Contentful the administrators of the content types would have to create the properties themselves and decide how they would be presented for editing. This is done in a few steps where we first decide which type of property we want:

startpage property types

In our case we might want a title field to indicate the title of the startpage, a good choice for that would be a text property.

startpage new text field

We would then configure the look and feel of the field and add things like validation.

startpage additional validations

There are a bunch of other settings as well to really configure how this property should behave while creating our content.

In the EPi case we might decide to store comments and likes in separate database (probably not the EPiServer DDS though…) or perhaps as some sort of contenttype, like a comment block.

In Contentful we’d create a few more ContentTypes and link them together using a Reference property:

reference field

Conceptually we’re doing the same thing as in EPiServer. Every startpage/articlepage can have many comments and likes.

Once we have all this set up correctly we can start consuming our content. In the EPi-case we’d setup controllers and views to present the content using our @Html.PropertyFor helper method, in Contentful we call the contentful API and get our content returned as JSON.

There are two separate APIs that we can call:

  • Content Delivery API
  • Content Management API

As you can probably guess we call the first one (Content Delivery) when we want to present content, but not modify it in any way. The Content Management API is called when we need to add/delete/update parts of our content.

Calling the Contenful API is crazy simple, just make a get request specifying what content you want and supply a correct access token and you’re good to go.

For example to get all created articlepages for our site we might call the api something like this:

https://cdn.contentful.com/spaces/space-id-here/entries?access_token=this-is-the-accesstoken&content_type=articlePage

This would return a json object containing all of our articlepages.

{
  "sys": {
    "type": "Array"
  },
  "total": 1,
  "skip": 0,
  "limit": 100,
  "items": [
    {
      "sys": {
        "space": {
          "sys": {
            "type": "Link",
            "linkType": "Space",
            "id": "space-id-here"
          }
        },
        "id": "entry-id-here",
        "type": "Entry",
        "createdAt": "2016-04-13T17:37:35.831Z",
        "updatedAt": "2016-04-13T17:37:35.831Z",
        "revision": 1,
        "contentType": {
          "sys": {
            "type": "Link",
            "linkType": "ContentType",
            "id": "articlePage"
          }
        },
        "locale": "sv-SE"
      },
      "fields": {
        "title": "About us",
        "body": "Hello! This is the about us page."
      }
    }
  ]
}

We would then consume this JSON as we see fit and present the actual content to our visitor.

There are official SDKs available for many major languages, Ruby, Node.js, pure javascript, Swift, Android etc. There’s yet no official .NET SDK, but there’s an unofficial third part SDK that you can find here.

The pricing model is also highly attractive as compared to many of the commercial competitors. Up to 1000 content items, 3 users and 100k api-request/month is absolutely free. More than that costs from $99 to $199 a month depending on your needs. There’s also an enterprise model for companies with even greater demands.

As the api is rate limited it becomes very important to manage the amount of api-calls you make. Ideally you might want to cache the content returned from the API until they’re updated.

Heads up!

As I wrote this blog post the good people of Contentful reached out to me and pointed out that they have multiple layers of internal caching. Both at the CDN level and below. They do not normally recommend that you cache at your application level as it is simply not necessary and adds unnecessary complexity. Also requests that hit the cache do not count towards your rate limit, which is fantastic!

However, to make a point about the excellence of web hooks I’ll leave the short example below unaltered. But be advised that for an absolute majority of applications built on top of Contentful you would not have to implement any caching at all!

The problem with that would be that you need to be notified somehow when content is updated or created. Thankfully, being a modern and flexible platform, Contentful has embraced the concept of web hooks which make it dead simple to subscribe to events such as publishing, deleting and updating of content. We can set up a webhook for lots of different events and as the image below shows:

webhooks

This in conjunction with some clever caching would mean that you can keep the actual api-requests to a minimum while still responding instantly to content updates.

Is everything greener on the other side?

All in all I find the idea of separating content from presentation highly appealing and I hope that more companies start to look at this approach to content management. Not only is it beneficial for the content editors, being able to work without the interference of new code being deployed, without waiting for new properties to show up or bugs to be fixed, it is also highly beneficial for us developers; Being able to focus solely on the website/application consuming the content and not waste any time struggling with outdated CMS APIs and frustrating legacy wysiwyg editors.

That said though, change is always painful in one way or the other. I believe many EPiServer editors of today would feel a little lost without their trusty page tree representing the hierarchy of their pages. They might also miss the “on-page editing” capabilities introduced in EPiServer 7. Perhaps they’ll shed a tear for the dynamic properties, or maybe not…

I do believe, however, that they will love the lean, clean and intuitive edit interface in Contentful. The modern approach to handling digital assets (everything from markdown, to code, to video, images etc.) and the simplicity of creating content.

Change might be painful, but change is also inevitable. As the slow, ponderous behemoth CMSs of the past struggle to keep up with an ever changing and evolving web where front end frameworks have the life span of a dragonfly and major corporations change the rules for everybody, they might just see themselves get outpaced by the small and the nimble. And nimblest of them all is Contentful, CMS of the future…