At dotCMS we are committed not only to allowing authors to create content with ease, but also to deliver that content for developers to use in any desired channel.
Our Page API is a great resource that allows developers to render pages with any JavaScript framework. In addition, we provide the @dotcms/client library to interact with the dotCMS APIs and the @dotcms/react and @dotcms/angular libraries with components and hooks that will build the page for you. Moreover, dotCMS has featured native support for GraphQL since version 5.1.
Today, we’ll look at how to combine these features.
What is GraphQL?
GraphQL is an open-source data query language for APIs. It enables users to specify exactly what data they would like to retrieve from the server.
GraphQL performs three key tasks:
Allows the clients to pick exactly what they want
Uses a type system to describe data
Obtains data from multiple server resources in a single call
GraphQL vs. REST: What’s the Difference?
REST (Representational State Transfer) is a popular method for designing web APIs, utilizing HTTP requests to manage data through operations like GET, POST, PUT, and DELETE. While REST allows structured access to resources and stateless calls between applications, it often returns excessive data, including unwanted metadata, which may not be efficient for the client's needs.
GraphQL addresses these shortcomings by allowing developers to specify exactly what data they require in a single query. This results in the server returning only the requested data. DotCMS has integrated GraphQL support into its Java CMS, allowing developers to query content types, HTML, categories, and personas as collections without Java coding, similar to using Elasticsearch, thereby enhancing data fetching and schema generation capabilities.
Request a page from dotCMS GraphQL
The GraphQL API for dotCMS is in the URL: /api/v1/graphql. Fetching data from a GraphQL endpoint is a little different from REST; that’s why there are some JavaScript libraries commonly known as “GraphQL Clients” — for example:
Relay
Apollo Client
Urql
In our case, and for the simplicity of this blog post, we are going to use a simple fetch request.
The GraphQL query
To render a dotCMS page and make it editable in the Universal Visual Editor we need some specific properties. In our example, we wrote a function that generates the query based on the parameters we pass, the important part here is the query fields requirement.:
function getGraphQLPageQuery({ path, language_id, mode}) {
const params = [];
if (language_id) {
params.push(`languageId: "${language_id}"`);
}
if (mode) {
params.push(`pageMode: "${mode}"`);
}
const paramsString = params.length ? , ${params.join(", ")} : "";
return `
{
page(url: "${path}" ${paramsString}) {
title
url
seodescription
containers {
path
identifier
maxContentlets
containerStructures {
contentTypeVar
}
containerContentlets {
uuid
contentlets {
_map
... on calendarEvent {
# Related Contentlet
location {
title
url
# Related Contentlet
activities {
title
urlMap
}
}
}
}
}
}
layout {
header
footer
body {
rows {
columns {
leftOffset
styleClass
width
left
containers {
identifier
uuid
}
}
}
}
}
viewAs {
visitor {
persona {
name
}
}
language {
id
}
}
}
}
`;
};
In this query, there are a few key properties that our rendering library required to render the page:
The page properties, here you can get all the fields you will use from the page, that include title, url, path, and all other custom fields you need from the page content type, for example SEO fields.
viewAs, we use this to get the page information about persona and language.
The layout property is critical because it is what we use to render the rows, columns, containers inside the page, and it has the reference to the contentlets.
And finally the container, we require the container information like the identifier or path, how many contentlets can fit (maxContentlets) and what contentlet types can accept with the contentTypeVar.
The actual contentlets came in the containerContentlets where you can use GraphQL fragment spread to define custom fields for each contentlet type.
All this information is needed to properly render a dotCMS page but, of course, this query will vary depending on your content structure, specially the page property and the contentlet fields.
Rendering the page
Once we have the content from GraphQL, we provide our SDK with rendering pages for React @dotcms/react and Angular @dotcms/angular both will work with the GraphQL. In this example, we’re using React.
But before passing the data to the React or Angular components, we need to perform some serialization in the data delivered by dotCMS GraphQL endpoint. We provided the graphqlToPageEntity function in our client SDK that you can import to help with this.
This is the updated data that you will provide to the dotCMS Angular and React components. The detail of all this implementation lives in our nextjs example.
Javascript
import { graphqlToPageEntity } from "@dotcms/client";
import { DotcmsLayout } from "@dotcms/react";
export default async function Home({ searchParams: {path, language_id } }) {
const data = await getGraphQLPageData({
path,
language_id
});
const pageAsset = graphqlToPageEntity(data);
return <DotcmsLayout pageAsset={pageAsset}></DotcmsLayout>;
}
Conclusion
GraphQL ensures efficient data fetching, which is especially effective when used with dotCMS's capabilities to render pages dynamically across different JavaScript frameworks.
This synergy between GraphQL and dotCMS simplifies developers' workflows, making it easier to deliver tailored content experiences while maintaining high performance and scalability.