The Headless CMS
In a standard, or monolithic, CMS architecture, there will typically be a user interface for authors to manage content, a database to store said content, and a presentation layer or pages that display content to an end user upon request.
While this architecture can often times sufficiently fulfill project requirements, challenges can arise due to the coupling of the content repository with the presentation layer. A monolithic CMS will typically require developers to develop on top of the CMS, forcing them to follow languages, patterns, standards, and rules set by the CMS. This coupling can restrict flexibility, increase code complexity, and reduce maintainability.
Headless CMS architecture, or decoupled CMS architecture, aims to remove many of these challenges by decoupling its content from its head, or front-end. It’s tasked with managing and delivering its content through a RESTful API without any regard to how that content is displayed once it is consumed.
A headless CMS allows us to separate concerns, streamline development, remove front-end restrictions that come with a monolithic CMS, facilitate publishing to multiple platforms, and future-proof our content.
AEM as a Headless CMS
Adobe Experience Manager uses the Apache Sling [https://sling.apache.org/] web framework. Apache Sling comes with a DefaultGetServlet that provides functionality to facilitate using AEM as a headless CMS out of the box. The configuration for that servlet can be found at /system/console/configMgr/org.apache.sling.servlets.get.DefaultGetServlet. This servlet allows us to pass in a number or .infinity as the last selector to any node in our content (the number determines the recursion level to use) followed by .json as the extension. Doing so will return a JSON rendering of the content of that node and nodes underneath it depending on the recursion level specified in the selector. Additional information around rendering content with Apache Sling can be found in Apache Sling – Rendering Content – Default Get Servlets documentation. [https://sling.apache.org/documentation/bundles/rendering-content-default-get-servlets.html].
As an example, let’s say we have an AEM Experience Fragment located at /content/experience-fragments/my_experience_fragme/a-new-fragment and we want that content to be provided to some other rendering platform. We can provide that content through /content/experience-fragments/my_experience_fragme/a-new-fragment.infinity.json. We should get something similar to the following (although the figure shown below is just a snippet of what you’ll likely see):
jcr:created: “Wed Jun 14 2017 11:10:13 GTM-0600”,
jcr:title: “A new fragment”,
cq:tags: [ ],
jcr:created: “Wed Jun 14 2017 11:10:13 GTM-0600",
jcr:title: “A new fragment”,
The JSON delivered contains the content from the Experience Fragment, including all of its variations. If we want a specific variation, we just dig a bit deeper. For example, if we want to get a Facebook variation that we may have created using the Experience Fragment Template Facebook template, we’ll add that node name to our request: /content/experience-fragments/my_experience_fragme/a-new-fragment/facebook.infinity.json.
This is all out of the box functionality. If the DefaultGetServlet doesn’t fit your needs, you can always create your own servlets to provide functionality specific to your situation.