Skip to main content

NextJS applications

Setup

First of all, it is necessary to setup the connector by following the Setup section, copying the discovery-cms-connector.js file inside the public folder and adding the following inside the _app.js file scripts:

<script async={true} src={'discovery-cms-connector.js'} />

Using the Akamai loader

If you use Akamai Image Manager and want to use next/image you need to define a custom image loader as follows:

// file: lib/akamaiImageloader.js
export default function akamaiImageLoader({ src, width, quality }) {
if (src.includes('?')) {
return `${src};Resize,width=${width}`;
} else {
return `${src}?imwidth=${width}`;
}
}

edit next.config.js to point to the Akamai loader:

module.exports = {
...
images: {
loader: 'custom',
loaderFile: './lib/akamaiImageloader.js',
remotePatterns: [{
protocol: 'https',
hostname: '<YOUR-AKAMAI-DOMAIN>',
}],
},
};
...
}

In remotePatterns.hostname you must indicate the Akamai domain. The remotePatterns section is explained here.

IMPORTANT: Without this change, if you use Vercel your images will all pass through the Vercel CDN. Check your account's bandwidth limits.

Client Side Generation

In a NextJS application, in addition to client side management, seen in React, you need also consider static and server side generation where the data representation part remains unchanged to a React application, but it changes how the data is retrieved.

Server Side Generation

During server-side generation, you can retrieve data using the connector within the function getServerSideProps:

export async function getServerSideProps(context) {
const data = await getDiscoveryCms().getPage('slug');

return {
props: {
date: date
}
}
}

By doing this it is no longer necessary to recover data with useDiscoveryPage or useDiscoveryContent.

Static Site Generation

During static page generation, you can retrieve data exactly as shown for SSG, obviously using the correct NextJS method:

export async function getStaticSiteProps(context) {
const data = await getDiscoveryCms().getContent('Slug');

return {
props: {
date: date
}
}
}

StaticPaths

When using static generation in combination with dynamic pages (e.g. [slug].js), it is necessary recover the paths for which it is necessary to generate a static page. The path array can be generated using the getPathList method which returns an array of objects

{
slug: 'some-slug'
}

Starting from this array, it is possible to apply a transformation to obtain the format required by NextJS:

export async function getStaticPaths() {
let paths = await getDiscoveryCms().getPathList({ type: 'ContentType' });
paths = paths.map((path) => ({
params: {
slug: path.slug,
},
}));

return {
paths: paths,
fallback: 'blocking',
};
}

Preview Mode

NextJS provides the Preview Mode which allows the viewing of changes to static pages, without having to build the application and expose those changes to the public. This is done using a cookie that the application uses to regenerate the page for clients in possession of this cookie, allowing changes made on a website to be displayed in real time headless CMS without having to rely on other environments. The Discovery CMS supports preview mode through a few simple adjustments. First you need to activate two endpoints:

  • api/preview: allows you to enter preview mode
  • api/exit-preview: allows you to exit preview mode.

To do this, you need to copy the two related files from node_modules/@discoverycms/connector/nextjs into the pages/api folder of the project. While the output endpoint can take different paths, the preview mode activation endpoint must necessarily be api/preview.

Next, you need to add the DISCOVERY_PREVIEW_TOKEN environment variable to your .env file, setting it to the value of the preview token provided by the CMS.

Once this is done, in the _app.js file, it is necessary to acquire the information relating to whether the preview mode is activated or not using the useRouter() hook and adding the data-preview-enabled data attribute to the script that integrates our discovery-cms-connector.js file like this:

<script id="connectorScript" async={true} src={'/discovery-cms-connector.js'} data-preview-enabled={router.isPreview} />

At this point, by accessing the page through our CMS, the preview mode will be automatically activated and the token with which to access the preview version of the data will be present inside the context passed to the getStaticProps and getServerSideProps methods. It will therefore be necessary to modify these methods, in the part relating to the call to the Discovery connector, passing this token if present:

     const data = await getDiscoveryCms().getPage(
'home',
{
...context.query,
token: context.previewData?.token// We pass the token present in previewData if present
}
);

This will allow, during the build phase, to use the public token and generate the correct page, while, in the preview mode phase, to regenerate the page using preview data and allowing the user to correctly view the changes he makes to the page without having to make them public.

It is worth remembering that the use of Preview Mode is required in case of SSG. In the case of CSR, this approach is not foreseen, as it would expose the preview token to the public. In this case, the display changes in phase of edit is done using the token that is passed from our CMS to the page, via param token query, and which must be passed to the options of the various connector methods. Without this step, it would not be possible to see the changes in real time. Finally, in case of SSR, it is possible to use both methods proposed above. In fact, SSR mode supports Preview Mode but also allows you to access query params on every request. It therefore remains the developer's discretion to decide which approach to use.

As a final note, it is worth remembering that using Preview Mode could scare the user. In fact, once activated, the mode remains active for 2 hours and, above all, it is also active by accessing the site directly without going through the CMS. It is therefore important to communicate to the user whether or not to use it of this mode, showing a clearly visible element that communicates this and allows you to return to the public version. To do this it is enough insert a link to the api/exit-preview endpoint.