In Jonathan Haidt’s 2012 book, “The Righteous Mind: Why Good People Are Divided by Politics and Religion,” he mentions a study where subjects were shown pictures of a furnished room and asked to describe it.
Subjects from capitalist countries tended to describe the individual items in the room (“there’s a couch and a lamp”) while subjects from more socialist countries tended to describe the entire room (“it’s a living room”).
One group of subjects was perceiving the objects. The other group was perceiving the larger whole which emerged from the combination of the objects.1
The point was that our concept of the role government should play in our life is deeply rooted in our conception of individuality opposed to the aggregation of people into a community. Or vice-versa, I suppose — one’s experience with government probably influences how we see everything else.
But, the point remains — do we perceive objects, or aggregations of objects? And does the appearance of an object with another object change the nature of both?
I know, this is a bizarre start to a post about CMS, but stick with me —
What is that ineffable quality that makes a CMS? We’ve been structuring and recording information for millennia. We’ve had relational databases for decades. But what is it that makes a data repository a CMS?
I think headless CMS has forced some soul-searching onto the larger CMS landscape. It’s driving a discussion of what a “CMS” even is. How big is that umbrella, and where is the boundary between what is a CMS and what isn’t?
I’ve been wrestling with this question for over a decade. See “What Makes a Content Management System” from June 2007. In that post, I took a feature-based approach to the question — what is and isn’t a CMS is just a super-set of features above a relational database.
But, lately, I think it’s more subtle than that.
I think the soul of a CMS lies in its ability to reason about abstractions. A CMS can interpret and respond to an abstracted, intentional request — don’t just give me a specific content object, but rather here is my need, and respond with the bundle of content structured in such a way that meets that need.
(I’m reminded of my wife, who is a kindergarten teacher. My wife gets kids like no one else. She understands that a child actually says, of course, but more importantly, she understands what a child doesn’t say. My wife can evaluate a child and understand their need, which is far above what they can merely articulate in verbal form.)
I hate to use the word “experience,” I really do. First, it’s hopelessly over-used. Second, it’s conflated with specific features. Third, it cracks open the gaping abyss of marketing hyperbole into which we might get sucked for all eternity.
But it fits.
Remember that a visitor knows nothing of your content model or objects. They don’t know a Text Page from an Article Page, or what Content Object #234 looks like.
And the products page of your website is not content. It’s really an experience. It’s made up of content, for sure. But the request for it is an intention that needs to be interpreted and formed into a “payload” of content to provide an effective response.
Put another way, when a visitor requests “/products”, they’re not saying “Give me Content Object #234.” Rather, they’re saying, “I have a need. Give me an experience that fulfills it.” Visitors don’t perceive actual content; they perceive the experience of content.
I gave the developer keynote at Sitecore Symposium this past October. In that talk, I set forth a five-layer model for what constitutes a “CMS.” It looked like this:
- Modeling and Aggregation: this the ability to describe content, relate it to one other, and organize it into structure that provide value
- Editorial Tools: these are the tools that allow editors to work with content — so, the editorial UI at the most basic level, plus other tools like versioning, workflow, preview, etc.
- Response Logic: hold this thought — we’ll come back to this below
- Delivery and Presentation: the ability to transform raw content into a form suitable for consumption, and inject it into a consumption channel
- Optimization: the ability to impact the performance of content post-publication — things like personalization, A/B testing, etc.
I grouped the first two layers — Modeling and Aggregation and Editorial Tools — under the label of “repository services.” These two things are needed to provide the ability for editors to work with content. They need some sort of UI to manipulate it, and they need the rules and storage mechanisms to hold onto it.
These repository services are all that a headless CMS aspires to be, almost universally. In fact, the entire pitch of headless right now seems to be, “We do only this thing, and we do it well, so you can fill in the other layers however you see fit.”
At Symposium, I made the case that this makes it tough to even call these systems a “CMS.” True, that term is applicable in a purely semantic sense: a headless CMS is a system that allows you to manage your content. But, in the years since “CMS” became a term, it’s become a colloquial shorthand for a system that provides all the layers (with #5 being more recent, and more common in the commercial space).
I argued that a headless CMS should really be called an “HCR,” or a “headless content repository.” Honestly, the “headless” qualifier is perhaps redundant. In their most pure form, these systems are simply content repositories.
Don’t interpret this as a pejorative term or a value judgement. Content repositories are critical, and they’re the technical basis for everything we do with content. A good repository is a wonderful thing.
But remember, repositories are about content, not about experiences.
I’m beginning to think the line of differentiation between repository and CMS is layer #3 from my model above: what I’m calling “response logic.” With a traditional CMS, there’s a layer of logic that can interpret intentions and choreograph a response of multiple content objects, organized into a larger structure, to provide an experience.
Digging deeper, let’s take a second to establish a couple precepts —
- First, every CMS responds to requests. At one level a CMS is simply a database. We make a request of it — either a URL is requested, or an API is invoked — and the CMS responds by providing content.
- Second, requests can be for one of two things: (1) specific content, which is common from an API (“give me content ID #234”), or (2) some abstracted representation of a payload of content (“I want the URL ‘/products'”).
Response logic, then, are the rules and processing a CMS uses to respond to a request. We can further sub-divide this logic into two parts:
- Transactional response logic, which simply manages the transactional details of providing a piece of content
- Abstraction response logic, which interprets request abstraction and determines what specific content should fulfill it
For a specific content object (ID #234, in our example), transactional response logic performs these steps:
- Access Control Checking: is this security context allowed to view this content?
- Publication Status Checking: is this content assigned a state that allows viewing?
- Version Selection: which version of this content is the published version?
- Variation Selection: is this content being personalized or multivariate tested, and, if so, what combination of variations should be presented?
This is where headless systems really stop. Headless CMS requires you to manually identify or query content, much like SQL against a database, so that’s what they do.
But that isn’t the interesting part.
Abstraction logic can interpret a non-specific content request (“/products”, in our example), and do this:
- Abstraction mapping: in WCM, the abstraction “name” would be a URL, so the CMS has to map the URL to a specific content object in the repository. Generally, speaking abstractions link to specific content objects, but that object might be nothing more than a query that aggregates more content (a view from Drupal Views, for example)
- Contextual content association: the CMS needs to then gather all the content of the response payload, and it needs to run all the transactional rules on each
So when someone requests “/products”, our CMS has to figure out what content represents that view (likely a “Text Page” called “Products”), then determine everything else that needs to be rendered with it: content to form the menus, crumbtrails, header media, related content, etc.
All this content together is the “response payload.”
And this is where we cross the line into what I would call a “CMS”: something that has the ability to respond to abstracted content requests. It has a layer of knowledge of just what needs to happen when someone wants “/products”, or when they’re looking at the home screen of your app, or all the content necessary to fully-render your white paper into a PDF.
A traditional CMS has always played the role of ringleader — it was the dispatcher that translated the intention of abstraction requests into the actual content required to fulfill it. A system that exchanged intention for experience.
With a content channel based on a headless system, where is this response abstraction logic? As we’ve established, it’s not in the repository. It’s either baked directly into the delivery layer, or it’s something between the delivery layer and the repository.
- You might have URL queries embedded in PHP code that directly executes on request
- You might have a .NET framework that maps abstractions to backend queries via a BFF
- You might have a React component that makes queries for specific objects to form an aggregated display
Something, somewhere, has to choreograph a response payload. Regardless of where you put this or how you codify the rules, this is response logic. A traditional CMS has it built-in, while the current slate of headless CMS requires you to bring it with you.
This tacit ability for a CMS to choreograph an intentional request into a coordinated response of content is, in some senses, the “soul” of a CMS. It’s the thing that makes a CMS more than just a database. It’s what makes a CMS a CMS.
An interesting aspect of response logic that we can use to speculate on the future of headless is that response logic embraces convention. Indeed, response logic is convention. It’s some larger framework for converting a request abstract into a response payload.
I promise that if you build response logic enough times, you’ll come up with common rules and practices for mapping request abstractions into content payloads. You’ll do the same things over and over again until patterns emerge. You’ll eventually codify those patterns, and before you know it, you’ll have developed a response logic layer.
And this is what I think we’ll see in the headless space: commoditized response logic. Someone, somewhere, will come up with a framework to add response logic to a particular headless CMS. They’ll package this into a system and sell it or release it to open-source. Then, that headless CMS will have some new remote API abstraction “on top” of their existing API. The abstraction API will take some shorthand request (like “/products”), translate it to all the calls required to form the response payload, then assemble it and send it back.
So, you won’t build stuff directly with Contentful or Kentico Cloud. You’ll build something with “The Headless Whizbang Experience Manager 5000”, and some headless repository will be abstracted behind it. (And just watch — they’ll be interchangeable, so you can use Whizbang with a plethora of backing repositories.)
(This could most easily happen with some MVC framework. Even now, an MVC framework is a form of response logic — it converts an inbound request abstraction into executable code. Someone, very soon, will release some code that maps models in an MVC framework to content objects in a headless content repository.)
Could headless systems build response logic in? Well, yes, of course, but their marketing message has always been a rejection of it, so they’ll likely leave it to other software (or build it themselves as a separate product).
But the easiest way do start down this road is to allow URL rewriting/aliasing on the inbound request.
I mean, wouldn’t it be handy if we could alias this…
http://headless-cms.com/ my-account/ items/ ?select=id,title,summary &type=blog-post &sortby=date &sortdirection=desc &limit=3 &auth=[key]
Even something as simple as that moves us from content to experience. The former is an intention (“tell me what’s new in your world”), the response to which constitutes an experience. The latter is simply the mechanics that gets us there.
Abstractions like this would be helpful to centralize logic. If you have your app installed on 10,000 devices and one day you decide you want to show the top four blog posts instead of the top three, wouldn’t it be handy to be able to change the backing querystring for the “/recent_posts” URL? Wouldn’t it be nice to have some cushy layer of configurable logic rather than just fielding raw queries all day?
(What? You already do this via a BFF or proxy? Well congratulations, you just wrote some response logic.)
The pitch of headless always fixates on templating and rendering. “You can use React!” or “Angular!” or whatever else! It’s as if the last mile of concatenating a string of HTML is the single biggest problem we have to solve.
It isn’t. Templating is actually the easy part.
Rather, I think that the headless CMS category has been defined by an explicit rejection of response logic, and, by extension, a rejection of experience in favor of raw content.
The current spate of headless systems are trying to be super-content-databases that just respond to raw queries without any regard to the experience that a choreographed response is meant to represent. You need to bring your own experience manager.
And, to be fair, this is the point. They’re not ignorant of experience, they just trust you to handle it yourself.
But at some point, I think we’re gonna miss this. We’re going to find ourselves re-implementing it enough that we realize there are patterns there, and how can we develop some commoditization around it?
And this might be the next step for headless: how do we allow our customers to develop response logic at the repository level? How do we move headless systems from just managing content and responding to requests, and rather start managing an experience of content at the perceptual level?
It’ll be interesting to see if they go in this direction.