Thomas Lund Sigdestad Enonic

I am Enonic's CTO, Thomas Sigdestad. I recently had a presentation about the new version of Guillotine, and how to dynamically extend the GraphQL schema. As the title suggests, it goes beyond the traditional headless CMS features. This is the next iteration of CMS, and we think it's really cool. You're the first to get a live demo of it, and I hope you'll enjoy it.

Guillotine 7 - Dynamically Extend the Enonic Headless API

What is Guillotine?

If you're not familiar with Guillotine, it's essentially Enonic's Headless API. We take headless seriously, which is why it's called Guillotine. It's a GraphQL API, meaning it's strongly typed and automatically generates the API based on your content model.

Whenever you define content types and other schemas, the API automatically reflects those changes. Guillotine is available as an app on Enonic Market, so you can simply install it and get everything out of the box. Like almost everything else we do, it's open source, so you can dive deep into it if you're interested.ย 

Even though this is version 7, it is a major rewrite. We had to make significant changes to enable the functionality I'm going to demonstrate. The big news is dynamic extensions, which we'll focus on here. What does that mean? We'll show you in the demo.

Beyond Headless CMS

What do I mean by "beyond Headless CMS," and why is this important? Traditional CMSs tried to do everything: front-end rendering, content management, personalization, and more. Then came headless CMS, reducing the CMS to just being a database. This shift impacted both editors and developers. Developers could use their favorite frameworks, but had to take on more responsibility, often reinventing things to make everything work together.

The next iteration, which I call universal CMS, combines the best of headless and traditional CMS. It offers the visual editing capabilities and functionality that editors enjoy, while also allowing developers to choose their own front-end frameworks. The CMS takes on a more significant role, delivering not just HTML, but also JSON and more.

Typically, a headless CMS includes an authoring interface, an API, and a content model. This is where it usually stops, with no room for expansion. However, with Enonic XP, you get a complete platform with back-end control, a JavaScript framework for server-side coding, security, storage, and more, making it a full application stack. On top of this, you have Content Studio and the Guillotine API.

When these elements come together, you have a digital experience back-end. This means you can integrate your systems and data through Enonic. For example, you can fetch real-time prices or accept and store user-generated content through the API. Enonic's general data storage allows you to persist data without needing additional services or databases, and you can deliver content in any format or platform.

Live Demo

Let's start from scratch. I have Enonic CLI installed. I'll create a sandbox, which is a local developer environment, running everything on my machine. We'll call it "my sandbox" and use the "essential" template, which pre-installs some applications.

After setting up the sandbox, I'll create my app called "myapp" and go into the folder to start compiling. This initial compilation takes a couple of minutes because it involves downloading dependencies.

While that's running, let's look at the local version of XP. This is the full platform, just like running a server in the cloud. There are shortcuts to log into the admin, and some apps were automatically installed when I set up the sandbox, including the one I just built. I'll skip straight to Content Studio, where I should now have sample data, including movies, pictures, and persons.

Because I have Guillotine installed and have super-user roles, I can start running queries instantly from Content Studio. I have a query that searches for content with the text "Morgan" and checks the content type "Person." It fetches the display name, date of birth, and photos, which are references to other content. Running this query retrieves the data.

Let's enhance this example by adding functionality to show Morgan Freeman's age without manual calculation. In the app I created, I'll add a folder called Guillotine and a TypeScript controller file.

To extend the API, we add a field using a creation callback. This manipulates and updates the schema, adding an "age" field to the "Person" data type. The resolver calculates and returns the age based on the date of birth.

I'll deploy the app again to ensure Guillotine detects the changes. Refreshing the query playground, I'll add the "age" field to the query for Morgan Freeman. Running it shows the calculated age. This demonstrates how you can extend the API to include additional data, potentially from other systems or aggregated within XP.

Next, I'll show a more sophisticated example by installing additional test data and the SEO meta fields app. Switching to a different dataset, a blog, I'll add the SEO app, configure it with a fallback image and other settings, and publish it. This app adds a preview panel and additional fields for overriding on each content item. In preview, the app injects the necessary meta properties.

For headless usage, the app dynamically extends the API. A new query fetches the site, front page, and blog post, along with the newly added meta fields. Running this query retrieves the meta fields, allowing the front end to use them directly. This showcases the dynamic capabilities of the CMS, providing a robust back-end for your front-end needs.

This is what we're also doing with all of our standard apps now. Whether you're using our framework or headless, you'll get the same functionality and capabilities. You can build even cooler things. For our site, we're using Next.js with headless, and we also use the sitemap app and the SEO app. Everything gets injected dynamically into the schema. You've seen this live now.

Q&A

Question 1: I know that sometimes we retrieve data that needs authorization. Can you elaborate on the security protocols for authorization?

Answer: When you're running a query and you might not be authenticated, Guillotine knows this and executes in the context of your permissions. For example, if there's a secret field or price data, it won't show unless there's authorization. You can set up virtual hosts to protect the API, or set up autologin. Guillotine is open, but the data isn't necessarily open. If a content item requires being a member of a developer group, it will not be retrieved unless authentication is provided with the request. So, yes, you can control and protect the data accordingly.

Question 2: It's great to be able to add custom fields to the Guillotine API. But what if two different apps decide to add the same field, for instance? One app adds a field, and the other deletes the same field. What happens then?

Answer: Short version: it's undeterministic. If two apps implement the same field, like the age field, the outcome is random based on which app starts first or changes last. The best practice is not to introduce two apps that do the same thing. Use namespacing or other methods to avoid conflicts.

However, with XP, everything is namespaced out of the box. If you have three applications with the same content type "person," they will have different names because the name includes the app and content type. You are in control of this yourself.

Guide to Composable CMS

Related blog posts

Get some more insights ๐Ÿค“


Get started with Enonic! ๐Ÿš€