TLDR:
In a Headless CMS (or a Decoupled CMS), the content retrieved by the front-end needs to be identifiable (somehow). This is where I'm stuck. I can describe my guesses of how platform-agnostic content might be made identifiable (see my attempt at a guess below). But I can't find real-world confirmation of tried and tested approaches anywhere, detailing how the decoupled front end can request the content from the content repository in a meaningful, indentifiable manner.
Where can I find a straightforward description of this core aspect of the mechanics of Headless CMS (or Decoupled CMS) architecture?
Recently I've been intrigued by the term Headless CMS.
There seem to be no shortage of articles and blog posts explaining:
- What is a Headless CMS?
- What's the difference between a Headless CMS and a Traditional CMS?
but the explanations always seem to be pitched at the reader who is planning to start using a Headless CMS, not at the engineer who wants to try their hand at writing a Headless CMS.
Eventually, after trying repeatedly to read between the lines of the articles I was reading, I grasped the single, fundamental innovation built into the Headless CMS:
- in Headless CMS architecture, content and structure are completely separated
A conventional approach in web development is to maintain substantial separation between:
- Structure (HTML)
- Presentation (CSS)
- Behaviour (JS)
In this model, the written and media Content isn't listed as a (fourth) separate concern because it's implicitly interwoven throughout the Structure.
e.g.:
- You can take the
HTML
markup:<button type="button">Launch Jaguar Slideshow</button>
- and present it as a big red button with capitalised white text and a drop-shadow using
CSS
- and enable it to trigger the creation and drop-down of a console, containing an animated slideshow using
Javascript
But what you can't conventionally do is separate the textual content:
- Launch Jaguar Slideshow
from the markup structure:
<button type="button">
...</button>
But - if I understand correctly - this is what a Headless CMS enables:
- on one page
<button type="button">
...</button>
may contain: Launch Jaguar Slideshow - on another page,
<button type="button">
...</button>
may contain: Launch Leopard Slideshow - on a third page,
<button type="button">
...</button>
may contain: Launch Tiger Slideshow etc.
I'm not even sure that I've understood everything correctly up to here - and I've never used a templating language - but, my first (incidental) question:
Does this, essentially, make a Headless CMS the conceptual child of:
- a Traditional CMS; and
- Templating Languages such as Mustache, Handlebars.js, HAML, Pug, Slim, Nunjucks etc.
with the addition that whereas the templating languages above tend to work exclusively with HTML
, the kind of templating engine in a Headless CMS will insert Content into any structure (ie. not just into HTML
in a web document, but also into the XML
of an RSS feed, or into a Social Media platform component, or into the UI structure of a Native App etc.)
and, my second, main question:
How on earth might one approach decoupling Content from Structure?
My best guess is something like the following JSON
, where I have tried to express the relationship of the content only to itself (so it remains structurally agnostic and can be queried and return data to slot into any structure).
{
"Summary":{
"Title":"Apples",
"Created":"[TIMESTAMP HERE]",
"Last Modified":"[TIMESTAMP HERE]",
"ShortDesc":"An 8-10 word description of Apples here",
"LongDesc":"A 20-30 word intro to Apples here."
},
"Related":{
"Parents":[
"Woodland_Fruit"
],
"Siblings":[
"Blackberries",
"Cherries",
"Pears"
],
"Children":[
"Granny Smith",
"Braeburn",
"Gala",
"Red Delicious"
]
},
"Media":{
"Images":{
"Hero_1":{
"Sizes":[
],
"URL":"[URL HERE]",
"Title":"Title Here",
"Alt":"Alternative text here",
"Created":"[TIMESTAMP HERE]",
"Credits":{
"Photographer":""
},
"Licence":{
"Type":"",
"URL":"",
"Holder":""
}
},
"Primary_1":{
"Sizes":[
],
"URL":"[URL HERE]",
"Title":"Title Here",
"Alt":"Alternative text here",
"Created":"[TIMESTAMP HERE]",
"Credits":{
"Photographer":""
},
"Licence":{
"Type":"",
"URL":"",
"Holder":""
}
},
"Associated_1":{
"etc.":"etc."
},
"Associated_2":{
"etc.":"etc."
}
}
},
"Editorial":{
"Primary":{
"Title":"Hesperides and Beyond",
"Author":"Ann Onne",
"Created":"[TIMESTAMP HERE]",
"Last Modified":"[TIMESTAMP HERE]",
"Last_Modified":"[TIMESTAMP HERE]",
"Sections":[
{
"Paragraphs" : [
{
"Paragraph": "[SECTION 1, PARAGRAPH 1 HERE]",
"Pull_Quotes": [
"PULLQUOTE HERE"
]
},
{
"Paragraph": "[SECTION 1, PARAGRAPH 2 HERE]",
"Pull_Quotes": [
"PULLQUOTE HERE",
"PULLQUOTE HERE"
]
}
]
},
{
"Section_Heading" : "[SECTION HEADING HERE]",
"Paragraphs" : [
{
"Paragraph": "[SECTION 2, PARAGRAPH 1 HERE]"
}
]
}
]
},
"Secondary_1":{
"Sections":[
{
"Section_Heading" : "[SECTION 1 HEADING HERE]",
"Paragraphs" : [
{
"Paragraph": "[SECTION 1, PARAGRAPH 1 HERE]"
}
]
},
{
"Section_Heading" : "[SECTION 2 HEADING HERE]",
"Paragraphs" : [
{
"Paragraph": "[SECTION 2, PARAGRAPH 1 HERE]"
}
]
},
{
"Section_Heading" : "[SECTION 3 HEADING HERE]",
"Paragraphs" : [
{
"Paragraph": "[SECTION 3, PARAGRAPH 1 HERE]"
}
]
}
]
}
}
}
(Hmmm. Does that begin to look like a pseudo-version of JSON-LD + Schema.org
to you? Because it does to me...)
The JSON
above describes the topic Apples
:
- It has 4 sections:
Summary
,Related
,Media
,Editorial
- It indicates that the topic
Apples
has a parent topic, as well as sibling and children topics. - The topic has associated media (a hero image, a primary image and 2 more associated images)
- The topic also has two Editorial "articles" - one is a proper article, one is supplementary information
So far, so good.
But most of this feels very much like guesswork.
I'd like to confirm that this sort of approach is on the right track.
Is this how I'm supposed to approach separating Content from Structure when building a Headless CMS?