Static pages and revalidation


In this chapter you will learn about NextJS' static site generation capabilities, and how Enonic triggers re-generation of pages when publishing.


Your NextJS front-end strives to use Static Site Generation (SSG) when possible which basically means you get lightning fast pages, but adds an additional compilation build step.

For more information visit the Next.js rendering documentation.

Task: Activate prod mode

So far, you have been running Next.js in dev mode.

By starting Next.js in prod mode, the application is automatically optimized, and in our case, pages get pre-rendered statically before the server starts.

Remember to stop your existing Next.js dev instance before you continue.
  1. Start Next.js in prod mode:

    npm run prod

    This will take a while longer as when compared to dev mode.

  2. Verify by pointing your browser to http://localhost:4242, you should now see the published items, just like in dev mode. Only this time, they will be much faster. Sweet!

Task: Fixing preview

With Next.js now running on a different port, Content Studio preview will stop working.

  1. Fix the preview by adding a Next.XP configuration file, with the following content to your sandbox:

    The configuration files are located in your sandbox home directory, which can be found in your users home directory as .enonic/sandboxes/<your-sandbox>/home/config/.
  2. Verify that the preview is working in Content Studio.

    Content Studio uses Next.js' preview mode, which automatically bypasses static pages - giving you a fresh preview of your draft content.

Task: Test page invalidation

With all pages now being cached as files, Next.js must be instructed to re-generate the pages when a change is published.

Edit your front-page, and publish the changes. This will trigger a revalidation hook, which is built into the Next.XP app.

The page should now get updated at http://localhost:4242 - more or less instantly.🎉

What happened?

In addition to handling previews, the Next.XP app automatically triggers revalidation of all pages when it detects the publishing event.

You should also be able to tell from the Next.js log that the revalidation was triggered.

A look at the code

Static Site Generation is controlled within the content page handler.

And the function we are interested the most is:

  • generateStaticParams() - This function will be used by Next.js at build time to create a list of pages to compile before the server starts.

Below, we explain the details of the code:

import {FetchContentResult, validateData} from "@enonic/nextjs-adapter";
import {fetchContent, fetchContentPathsForAllLocales} from "@enonic/nextjs-adapter/server";
import MainView from '@enonic/nextjs-adapter/views/MainView';

import "../../../components/_mappings";
import {Metadata} from 'next';
import {draftMode} from 'next/headers';
import React from 'react';

// NB. Using this option with default value bails out static generation !!!
// export const dynamic = 'auto'

// The revalidate option is only available when using the Node.js Runtime.
// This means using the revalidate option with runtime = 'edge' will not work.
export const revalidate = 3600

export type PageProps = {
    locale: string,
    contentPath: string[],

export default async function Page({params}: { params: PageProps }) {
    const {isEnabled: draft} = draftMode();`Accessing page${draft ? ' (draft)' : ''}`, params);

    const start =;
    const data: FetchContentResult = await fetchContent(params);
    const duration = - start;`Page fetch took ${duration} ms`);


    return (
        <MainView {}/>

export async function generateMetadata({params}: { params: PageProps }): Promise<Metadata> {
    const {common} = await fetchContent(params);
    return {
        title: common?.get?.displayName || 'Not found',

export async function generateStaticParams(props: { params: PageProps }): Promise<any[]> {
    return await fetchContentPathsForAllLocales('\${site}/');

As you can see, Next.XP provides methods to create static pages, but the best part is that it chooses the best rendering and caching scheme based on what your code is doing !

With prod mode and revalidation sorted out, let’s see how to add multi-language support.