Exposing Site Settings from the Settings item in a Headless JSS Next.js Application

In this blog post, we will explore a common requirement in Sitecore Headless SXA, exposing site-specific settings and global data to the front end when working with a JSS headless site.

Problem Statement

When building headless JSS sites, you often need to expose certain site settings or global configuration data from the Sitecore SXA Settings node to the front-end. However, the out-of-the-box Sitecore Layout Service primarily focuses on delivering route details (placeholders, data sources, fields, etc.), which may not fully cover the broader configuration needs.

In such cases, using GraphQL to query site-specific settings and integrating the results into the page-props is a reliable approach.

The Solution

To address this requirement, we can extend the Sitecore page-props to include site-specific settings. The approach involves:

  1. Extending the SitecorePageProps type to include site settings.
  2. Creating a GraphQL service to query and fetch the settings items.
  3. Adding a new plugin to the page-props-factory to populate the site settings into the props for every page.

Let's walk through the implementation step-by-step.

Implementation Steps

Step 1: Extend the SitecorePageProps Type

The first step is to extend the SitecorePageProps type to include a new property for site settings. We modify the src/types/props/page-props.ts file and add a new variable:

1export type SitecorePageProps = {
2  site: SiteInfo;
3  locale: string;
4  dictionary: DictionaryPhrases;
5  componentProps: ComponentPropsCollection;
6  notFound: boolean;
7  layoutData: LayoutServiceData;
8  headLinks: HTMLLink[];
9  SiteConfigurations: SiteSettingFields;
10};

Here, we introduce a new property called SiteConfigurations of type SiteSettingFields, which will hold the site settings data.

Step 2: Create a GraphQL Service to Fetch Settings

Next, we create a service to handle GraphQL queries and fetch the settings fields. We’ll create a new file called settings-service.ts inside src/lib/page-props-factory/services.

1import { GraphQLClient } from '@sitecore-jss/sitecore-jss';
2import { debug, GraphQLLayoutService, GraphQLLayoutServiceConfig, LayoutServiceData } from '@sitecore-jss/sitecore-jss-nextjs';
3
4export class GraphQLSettingsService extends GraphQLLayoutService {
5  private myGraphQLClient: GraphQLClient;
6
7  constructor(public serviceConfig: GraphQLLayoutServiceConfig) {
8    super(serviceConfig);
9    this.myGraphQLClient = this.getGraphQLClient();
10  }
11
12  public async fetchSettings(siteName: string, language: string): Promise<LayoutServiceData> {
13    const query = this.getQuery(siteName, language);
14    
15    const data = await this.myGraphQLClient.request<{
16      sitesettings: {
17        item: {
18          contentRoot: {
19            children: SiteSettingFields;
20          };
21        };
22      };
23    }>(query);
24
25    return data.item.rendered;
26  }
27
28  private getQuery(siteName: string, language: string) {
29    return `query {
30      sitesettings: layout(site: "${siteName}", routePath: "/", language: "${language}") {
31        item {
32          contentRoot: parent {
33            children(includeTemplateIDs: "{54BC031B-293F-46F6-8F98-CB4A9B37BDE2}") {
34              results {
35                sampleField: field(name: "sampleField") {
36                  jsonValue
37                }
38              }
39            }
40          }
41        }
42      }
43    }`;
44  }
45}

In this example:

  • We use the GraphQLClient to execute a query against the Sitecore GraphQL endpoint.
  • The query retrieves the children of the settings node, filtering by template ID ({54BC031B-293F-46F6-8F98-CB4A9B37BDE2}) and selecting the relevant fields.
  • The sampleField is an example field from the settings that we want to expose.

This service is designed to fetch the site settings from the settings node, specifically tailored for each site.

Step 3: Add a New Plugin to the Page-Props Factory

Now, we integrate the site settings into our page-props using a custom plugin. We create a file called get-settings.ts inside src/lib/page-props-factory/plugins:

1import { GetStaticPropsContext, GetServerSidePropsContext } from 'next';
2import config from 'temp/config';
3import { Plugin } from '..';
4import { GraphQLSettingsService } from '../services/settings-service';
5import { SitecorePageProps } from 'lib/page-props';
6import clientFactory from 'lib/graphql-client-factory';
7
8class GetSiteSettingsPlugin implements Plugin {
9  private settingsRequestClient: GraphQLSettingsService;
10
11  constructor() {
12    const siteName = config.sitecoreSiteName;
13    this.settingsRequestClient = new GraphQLSettingsService({
14      siteName,
15      clientFactory,
16      retries: (process.env.GRAPH_QL_SERVICE_RETRIES && parseInt(process.env.GRAPH_QL_SERVICE_RETRIES, 10)) as number,
17    });
18  }
19
20  order = 2;
21
22  async exec(props: SitecorePageProps, context: GetServerSidePropsContext | GetStaticPropsContext) {
23    const siteSettings = await this.settingsRequestClient.fetchSettings(
24      props?.site?.name,
25      props.locale
26    );
27
28    if (siteSettings != null && props != null) {
29      props.SiteConfigurations = siteSettings ?? {};
30    }
31
32    return props;
33  }
34}
35
36export const getSiteSettingsPlugin = new GetSiteSettingsPlugin();

Plugin Explanation

  • Order Property: The order = 2 ensures that this plugin runs after the core plugins (e.g., normal-mode and preview-mode). This is crucial because it allows us to populate the settings data before any layout data is processed.

  • Settings Fetching: We call the fetchSettings method to retrieve the settings data based on the site name and locale. The resulting data is stored in the SiteConfigurations property within props, making it accessible across the application.

Optimization Considerations

Since this GraphQL query runs on every page render, caching the results is recommended to avoid redundant requests and improve performance. Implementing caching at either the service or plugin level can significantly optimize the solution.

Conclusion

This approach gives you a clean and extensible way to expose site settings from the SXA settings node to your Next.js frontend. By integrating GraphQL queries into the page-props factory and leveraging custom plugins, we can make site configurations accessible across every page in the application.

Feel free to enhance this solution further with caching strategies or by extending the settings to include more complex data structures. Happy coding!

Related Posts

Exposing Site Settings from the Settings item in a Headless JSS Next.js Application

In this blog post, we will explore a common requirement in Sitecore Headless SXA, exposing site-specific settings and global data to the front end when working with a JSS headless site. ## Problem S

Read More

Handling Sitecore CM and IdentityServer Behind a Proxy or CDN in an Azure Environment

Recently, while working with a Sitecore 10.4 deployment in an Azure environment, we encountered an interesting challenge: handling Sitecore Content Management (CM) and IdentityServer (SI) behind a pr

Read More

Leveraging Sitecore Search SDK Starter Kit into Your Sitecore Next.js Solution [Part 2]

In this blog post, I'll walk you through the process of smoothly leveraging the Search SDK Starter Kit into a Sitecore Next.js solution. ## Prerequisites Before proceeding, ensure the following prer

Read More