Optimizely Graph and Next.js: Building Scalable Headless Solutions
Optimizely Graph harnesses the capabilities of GraphQL, an intuitive and efficient query language to, transform content within an Optimizely CMS into a structured, interconnected graph. Complementing this, Next.js, a React-based frontend framework, empowers developers to build performant and SEO-friendly web applications, enabling static and dynamic rendering and many more amazing features that can enhance your headless solution.
In this article we delve into the symbiotic relationship between Optimizely Graph and Next.js, exploring how this pairing facilitates the crafting of dynamic headless experiences, from enabling draft modes and On-Page Editing to harnessing static site generation. We'll also investigate the utilization of webhooks for efficient page revalidation, enabling seamless updates across web applications.
What is Optimizely Graph used for?
Using Optimizely Graph we are able to separate our admin panel from our application, the so called headless, since we have two separate applications that are independent of each other. Headless in Optimizely has long been possible by using the Content Delivery API, but Graph simplifies a lot of things.
How does Optimizely Graph work?
Optimizely Graph is a separate service that is hosted on a CDN, made fast by implementing the latest, most modern technologies using global serverless Edge computing, auto scaling microservices and the latest search engine.
There are two ways to deliver content to the Graph service:
- Scheduled job
- Event Triggering, for example publishing a page.
The Content Delivery API is used under the hood, delivering content to Graph. When you want to introduce something custom, such as adding business logic to a block, you can do so using an override of the serialization used in the Content Delivery API.
In the image below we can see how the Optimizely Graph works. It all starts in the admin panel, in the picture labeled with the Optimizely logo. From there, using the Content Delivery API, the content goes to the GraphQl Server. GraphQl Server is hosted on Azure and is embedded on a CDN. The GraphQl Server combines the admin panel and frontend application used by users. The frontend application communicates directly with GraphQl Server, receiving all the necessary data. Source: world.optimizely.com
Support for Commerce
As of early December, Optimizely Graph has been officially released and is production ready. The released version supports CMS only and allows read-only options. At a recent webinar held by Optimizely, the company said that they are getting a lot of requests for Commerce support and it is in the approval stage by Project Management. Keeping in mind that commerce is much more complicated than CMS, it may take longer to work on this. However, using other Optimizely products like Content Delivery API, we are able to implement Headless Commerce. There is also an option to use Graph for CMS-related stuff, and Content Delivery API for commerce-related stuff.
Personalization
Personalization as we know it so far, i.e. creating visitor groups and adding personalization in Content Area and XHTML strings, will not work.
Here's where other products can help, like Optimizely Web Experimentation, where you can create personalized campaigns and immediately measure which variance converts better. However, this is an additional product charged separately.
There is another option that is being worked on: the integration of Optimizely Graph with Optimizely Data Platform RLS (Real Time Segment), which is the next generation of “Visitor Groups”. ODP is also an additional product that is charged separately.
Content Recs
Content Recommendation works by scraping the page source of the site. if it is valid HTML, there should be no problem with it. If we use Server Side Rendering, there is pure HTML code in the page source, so with SSR, Content Recommendations works. The problem with Content Recs is that if you choose client-side rendering, it means that non-native HTML elements such as <teaser-block/> are included in HTML, so the scraper is not able to collect the correct data.
Hosting on DXP
It is possible to continue to have the frontend application hosted on DXP, then the client app (Node.js) and the backend (.net) are served on the same address by proxying requests from .net to the Node.js process. An example of such a solution can be found here Source: Github
Vercel is the recommended hosting platform for Next.js to fully leverage its capabilities, such as Incremental Static Regeneration (ISR) (example of code), image and font optimization. By hosting Next.js on Vercel, you can achieve better performance due to its seamless integration with Next.js and support for these advanced features.
Vercel's administration panel provides a user-friendly interface for managing deployments, making it accessible even to non-technical users. This allows for easy deployment to production after reviewing changes on staging. While there are inherent risks in allowing non-technical users to deploy changes, for small changes like increasing font size, the risks are minimal. The clear and intuitive interface of Vercel's administration panel makes it convenient for non-technical users to manage deployments with confidence.
An example of a starter for Optimizely Feature Flags with Next.js is available for preview and use here.
Understanding Next.js Rendering Strategies
Next.js employs three main server rendering strategies:
-
Static Rendering (Default): Routes are pre-rendered at build time or after data revalidation. The rendered result is cached and can be distributed via Content Delivery Networks (CDN). This strategy is suitable for static content like blog posts or product pages.
-
Dynamic Rendering: Routes are rendered for each user at request time. This method is ideal for personalized data or information specific to each user, such as cookies or search parameters.
-
Dynamic Routes with Cached Data: Next.js allows for routes with a mix of cached and uncached data. This flexibility means you can have personalized, dynamic content while benefiting from caching. For instance, an e-commerce page might use cached product data along with uncached, personalized customer information.
These server rendering strategies offer benefits like enhanced performance, improved security and better initial page load times. Leveraging Next.js's capabilities, developers can efficiently manage and render content, allowing for highly personalized and dynamic web experiences in your headless solution.
Fetching data from Optimizely Graph
@graphql-codegen/cli
Let’s configure our codegen. First, install following dependencies:
Now, we need to create a config file where we define plugins, schema source, destination file etc.
./src/types/generated.ts
./src/graphql/*
The variable:
is a generated base64 string based on your AppKey and AppSecret credentials. For more details I recommend you to take a look at Kunal’s article
optimizelyFetch
getSdk
./src/graphql
documents
After properly configuring codegen and firing the command that generates the SDK, we get a fully-typed client.
Draft Mode with Optimizely Graph and Next.js
With Optimzely and Next.js we can easily configure previews, drafts and on-page editing to fully take advantage of the headless architecture. In order to let Optimizely know what is the URL to our Frontend, we need to follow a few simple steps.
Manage Websites
/episerver/cms/content/**/*
Example:
is redirected to
Create an API route that will handle the draft mode:
[[…content]]
Let’s handle the draft mode in the Page component:
if
The optimizely script to utilize On-Page Editing feature:
data-epi-edit
To enable on page editing (OPE) we need to add an attribute to the html that will enable this, you can read more about it in the documentation
Static Site Generation
Static Site Generation (SSG) is a powerful feature in Next.js that enables the pre-rendering of pages at build time. During the build process, Next.js generates HTML files for each page in your application. These HTML files are static, meaning they represent the state of the page at the time of the build. The pre-rendered HTML files can be served to users without requiring server-side rendering for every request.
Benefits of Static Site Generation in Next.js:
-
Improved Performance: Since the pages are pre-rendered at build time, users receive static HTML files, reducing the need for server-side processing during runtime. This leads to faster page loads and improved overall performance.
-
SEO Optimization: Search engines favor static HTML content. SSG helps improve search engine optimization (SEO) by providing crawlers with easily indexable and readable content. This can positively impact a website's search engine ranking.
-
Lower Server Load: Static pages can be served directly from a content delivery network (CDN) without the need for server-side processing. This reduces the load on the server, allowing it to handle more concurrent users efficiently.
-
Cost Efficiency: Serving static content is typically more cost-effective than dynamically generating content for each user request. With SSG, you can generate pages during the build process, reducing the need for server resources during runtime.
-
Better User Experience: Static pages load quickly, providing a smoother and more responsive user experience. Users see the content faster, leading to higher user satisfaction and engagement.
-
CDN Compatibility: Static files can be easily distributed across a content delivery network, ensuring that the content is delivered from servers geographically closer to the user. This minimizes latency and further enhances page load times.
-
Offline Support: Static pages can be easily cached, enabling offline access for users. Once the pages are loaded, they can be stored in the browser cache, allowing users to access the content even without an internet connection.
How to Achieve This with Optimizely Graph:
In Next.js, there is a method called generateStaticParams that must return all static routes. To obtain this information, we need to query Optimizely Graph for all routes:
The GraphQL query to the Content Graph:
Implementation in TypeScript:
[[…page]]
In summary, Static Site Generation in Next.js offers a way to generate performant, SEO-friendly, and cost-effective websites by pre-rendering pages at build time. It leverages the benefits of static content while providing the flexibility and convenience of a dynamic web framework.
Using Webhooks for Page Revalidation (ISR)
Let's start by understanding what ISR (Incremental Static Regeneration) is.
Next.js empowers you to create or update static pages after building your site. Incremental Static Regeneration (ISR) allows you to utilize static generation on a per-page basis, eliminating the need to rebuild the entire site. With ISR, you can maintain the advantages of static pages while effortlessly scaling to millions.
In essence, ISR enables you to instruct Next.js to update the cache for a specific page and use the most recent published content.
Now the question arises: How do we know when the content in the content graph has been updated and returns the freshest content? This is where webhooks come into play. You can configure a webhook to inquire about content revalidation from the provided API when it's ready. The link to configure the webhook can be found here:
Optimizely Webhook Configuration
On this page, you need to choose the type of authentication. I opted for Header HMAC authentication (epi-hmac xxx), and the token used here is also employed for fetching unpublished content in draft mode. The token is a combination of AppKey and AppSecret. You can learn more about it here.
Before configuring the webhook, we need to create an API route that will handle the revalidation logic. For us, this route is api/revalidate
Tip:
To locally test the webhook communication, you can use ngrok tunneling. It will proxy your http://localhost:3000 to https and generate a randomly assigned link. After creating it, you can use that link for webhook configuration.
Webhook Configuration:
Example:
requestJson
GUID
RelativePath
All these components allow us to generate the entire site during production builds and return all pages from the cache. When we publish a new change to one of the pages, we only revalidate that specific page, enabling a seamless and efficient process.
Pros and Cons of Optimizely Graph and Next.js Headless Solution
Pros | Cons |
---|---|
Performance (SSR, SSG, ISR) | Additional layer of complexity |
Uses Edge | No support for Commerce |
Uses latest technology | A more expensive solution than the traditional Hybrid in terms of development |
Attractive for devs | Publishing content in CMS does not equate to an immediate change on the site |
Good SEO | |
A single source for content CMS -> web, mobile app… |
Optimizely Graph has several advantages, including improved performance through server-side rendering (SSR) and static site generation (SSG). It leverages edge computing technology and utilizes the latest technology stack, making it attractive for developers. It also offers good search engine optimization (SEO) capabilities and provides a centralized content management system (CMS) for managing content across web and mobile applications.
However, there are some drawbacks to consider. Implementing the solution adds an additional layer of complexity to the development process. It currently lacks support for commerce functionality. The development costs can be higher compared to traditional hybrid solutions. It's also important to note that publishing content in the CMS does not guarantee immediate changes on the website.
In summary, while the solution offers performance benefits, modern technology and a centralized content management system, it also presents complexities, limitations in commerce support and higher development costs. It's crucial to assess these factors based on specific requirements before deciding on its adoption.
Best Practices and Tips
Avoid using Apollo Client
Avoid using Apollo Client in your Next.js project. While it is a powerful GraphQL client, Next.js provides robust native support for fetching data using the built-in fetch
Next.js comes with several built-in features that make it well-suited for handling GraphQL requests. It provides extensive capabilities, such as cache tags and revalidation, making it unnecessary to rely on external heavyweight libraries like Apollo Client.
By sticking to Next.js native features and optimizing your GraphQL requests using the built-in fetch function, you can keep your project lightweight, efficient, and well-aligned with the framework's best practices.
Use Tailwind CSS
We recommend using Tailwind CSS as it provides an optimal solution tailored for Next.js. Tailwind CSS generates all styles during the build process into a single file, which is typically very small (in our Next.js projects, the CSS file is around 16-30kb). This approach enhances performance and aligns well with Next.js conventions.
UI Library
If you're in search of a UI library with versatile components, we highly recommend choosing Shadcn UI. It has proven to be an excellent choice in several of our projects. Shadcn UI offers extensive customization options and has consistently met all our requirements.
Use Codegen
Utilizing code generation alongside Optimizely Graph can save a significant amount of time. This is because you won't need to manually type page or block types. Code generation also creates TypeScript methods for interacting with Optimizely Graph. All you have to do is create a GraphQL query and run the code generation command. Notably, you can pass your custom fetcher, enabling customization according to your requirements.
Conclusion
In conclusion, the integration of Optimizely Graph and Next.js offers a powerful solution for building scalable headless applications. By leveraging GraphQL capabilities through Optimizely Graph, developers can structure and interconnect content within Optimizely CMS in a more efficient and intuitive manner. This is complemented by Next.js, a React-based frontend framework that enables the creation of performant and SEO-friendly web applications, supporting both static and dynamic rendering.
The symbiotic relationship between Optimizely Graph and Next.js allows for the crafting of dynamic headless experiences. This includes features like draft modes, On-Page Editing, static site generation, and efficient page revalidation through webhooks.
In summary, the Optimizely Graph and Next.js integration provides a robust foundation for developing scalable, performant, and SEO-friendly headless applications, with the flexibility to adapt to various use cases and requirements.
Hatimeria understands the importance of staying up to date with the latest trends in online business. That's why we have focused on mastering headless commerce to provide you with top-notch solutions. Our developers know everything about headless systems, decoupled frontend frameworks and powerful APIs, which allows us to create customized ecommerce experiences that meet your specific needs.
By using headless architecture, we can help you create seamless shopping experiences across different channels, improve website performance, handle increased traffic and give you more flexibility in managing your online store.
Don't miss out on the future of ecommerce. Partner with Hatimeria and embrace the limitless possibilities of headless commerce.
Would you like to innovate your ecommerce project with Hatimeria?
Football and Optimizely enthusiast. Able to conjure up goals not only on the pitch but also in a FIFA game. He is an Optimizely-certified developer and Fifa-certified player. When he's not delivering top-notch programming, he can be found in the gym honing his skills and training for the next game.
Read more Szymon's articles