Was this page helpful?

Using Experiences with NextJS

Table of contents

Using pages router

Server-side rendering using pages router

When using pages router in NextJS, you can render your experience on the server.

Important:

  • Use the vanilla JS fetchers (fetchBySlug or fetchById) inside of the server side methods (getServerSideProps or getStaticProps) instead of the React hooks useFetchBySlug or useFetchById.
  • The experience object returned by the fetchers is not serializable by NextJS directly due to their strict JSON serialization techniques. Therefore, we need to serialize the experience ourselves and pass the JSON string as a prop to the component.
  • In the component, we need to recreate the experience object from the JSON string by passing it to the createExperience function.

Below is an example page using NextJS SSR in the pages router:

import { createClient } from 'contentful';
import {
  fetchBySlug,
  ExperienceRoot,
  createExperience,
} from '@contentful/experiences-sdk-react';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';

const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';

const client = createClient({
  space,
  environment,
  accessToken,
});

function MyPage({
  experienceJSON,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  //Recreate the experience object from the serialized JSON
  const experience = createExperience(experienceJSON);

  return (
    <main style={{ width: '100%' }}>
      <ExperienceRoot experience={experience} locale={'en-US'} />
    </main>
  );
}

export const getServerSideProps = async ({}: GetServerSidePropsContext) => {
  const experience = await fetchBySlug({
    client,
    slug: 'homePage', //could be fetched from the context
    experienceTypeId,
    localeCode,
  });

  //Serialize the experience manually
  const experienceJSON = JSON.stringify(experience);

  return {
    props: {
      experienceJSON: experienceJSON,
    },
  };
};

export default MyPage;

Client-side rendering using pages router

When using client side rendering, fetching and displaying an experience is similar to how it is done in a normal single page application.

import React from 'react';
import { createClient } from 'contentful';
import {
  ExperienceRoot,
  useFetchBySlug,
} from '@contentful/experiences-sdk-react';

const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';

const client = createClient({
  space,
  environment,
  accessToken,
});

const MyComponent: React.FC = (props) => {
  const { experience, isLoading, error } = useFetchBySlug({
    client,
    slug: 'homePage', //Could be fetched from the url,
    experienceTypeId: experienceTypeId,
    localeCode,
  });

  if (isLoading) return <div>Loading...</div>

  if(error) return <div>Error: {error.message}</div>

  return <ExperienceRoot experience={experience} locale={localeCode} />;
};

export default MyComponent;

Using app router

Server-side rendering using app router

Currently, Experiences don't support server-side rendering using the app router in NextJS. We are looking into fixing this in an upcoming release. For now, your experience must be rendered client side.

Client-side rendering using app router

When using client-side rendering, fetching and displaying an experience is similar to how it is done in a normal single page application, except you add the 'use client' directive at the top of the component:

'use client';
import React from 'react';
import { createClient } from 'contentful';
import { ExperienceRoot, useFetchBySlug } from '@contentful/experiences-sdk-react';

const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';

const client = createClient({
  space,
  environment,
  accessToken,
});

const MyComponent: React.FC = (props) => {
  const { experience, isLoading, error } = useFetchBySlug({
    client,
    slug: 'homePage', //Could be fetched from the url,
    experienceTypeId: experienceTypeId,
    localeCode,
  });

  if (isLoading) return <div>Loading...</div>;

  if (error) return <div>Error: {error.message}</div>;

  return <ExperienceRoot experience={experience} locale={localeCode} />;
};

export default MyComponent;