dot CMS

Render dotCMS pages effortlessly with GraphQL and the JavaScript SDK

dotCMS
Author image

Freddy Montes

Product Manager

Share this article on:

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:

  1. 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.

  2. viewAs, we use this to get the page information about persona and language.

  3. 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.

  4. 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.

    1. 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.