3

There is a Sitecore Headless setup with SSG enabled. NextJS allows to show own 404 page but the requirement is to managed the page in CMS.

Quick solution was to extend the getStaticProps method in [[...path]].tsx file and just redirect to the /page-not-found:

export const getStaticProps: GetStaticProps = async (context) => {
  const props = await sitecorePagePropsFactory.create(context);

  // HERE: Redirect to /page-not-found:
  if (props.notFound) {
    return {
      redirect: {
        permanent: false,
        destination: '/' + props.locale + '/page-not-found',
      },
    };
  }
  return {
    props,
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 5 seconds
    revalidate: 5, // In seconds
  };
};

It works but there are few drawbacks. The url in browser changes which is odd. Besides that, the page status code is 200 instead of 404 which is not correct from the SEO perspective.

In order to fix that, instead of redirect, the CM/CD HttpRequestBegin pipeline has been extended as suggested in this post and this answer. Currently, request to CM/CD Layout Service returns proper NotFound page response with all the placeholders, renderings and status code 404:

https://cd.localhost/sitecore/api/layout/render/default?item=/missing-page&sc_apikey=xxx

{
  "sitecore": {
    "context": {
      "pageEditing": false,
      "site": {
        "name": "mysite"
      },
      "pageState": "normal",
      "language": "en",
      "itemPath": "/page-not-found",
    },
    "route": {
      "name": "Page not found",
      "fields": {...},
      ...
      "placeholders": {...}
    }
  }
}

The page is rendered correctly with NextJS. Browser URL does not change, but the status code is still 200... Even with the 404 responce from Layout Service... How to change it to 404?

2

1 Answer 1

2

When a new Next.js app is create a default 404 Page file is created.

This file is statically generated at build time.

import NotFound from 'src/NotFound';

const Custom404 = (): JSX.Element => <NotFound />;

export default Custom404;

If we want to customize the 404 page, we have to use getStaticProps to fetch data at build time.

To fetch data during build time in Sitecore we have to customize 404.tsx file.

Inside 404.tsx we need to fetch data from _404 error page.

import { SitecorePageProps } from 'lib/page-props'
import { sitecorePagePropsFactory } from 'lib/page-props-factory'
import { GetStaticProps } from 'next'

import SitecorePage from './[[...path]]'

export const getStaticProps: GetStaticProps = async (context) => {
  let props = { notFound: false }
    props = await sitecorePagePropsFactory.create({
      ...context,
      params: { ...context.params, path: '/_404' },
    })
  
  return {
    props,
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 5 seconds
    revalidate: 5, // In seconds
    notFound: props.notFound, // Returns custom 404 page with a status code of 404 when true
  }
}

export default function Custom404Page({
  notFound,
  layoutData,
  componentProps,
  navigation
}: SitecorePageProps): JSX.Element {
  return (
    <SitecorePage
      notFound={notFound}
      layoutData={layoutData}
      componentProps={componentProps}
      navigation={navigation}
      dictionary={{}}
      locale=""
    />
  )
}

The SitecorePagePropsFactory class uses an instance of the ComponentPropsService class that helps to identify which components require retrieval of data. The ComponentPropsService is provided by the NPM package @sitecore-jss/sitecore-jss-nextjs.

More information can be found here: https://sitecoreclimber.wordpress.com/2021/11/21/page-not-found-in-sitecore-headless-next-js/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.