Was this page helpful?

Set up Experiences SDK with Gatsby

Overview

This guide explains how to integrate a Gatsby project with Experiences from scratch. Throughout the guide you can use this completed Gatsby example set as a reference.

Set up Gatsby project and install Contentful dependencies

  1. npm init gatsby
  2. Pick a name and directory for your project. Select the following options:
    • Typescript: Yes
    • CMS: None
    • Styling system: None
    • Additional features: Done
  3. cd {project name}
  4. npm i @contentful/experiences-sdk-react contentful

Create the Contentful client

Create a Contentful client

A Contentful client enables you to fetch any experience entry based on your Contentful space and environment.

  1. Create a file named useContentfulClient.ts in the /src/utils directory, so the file path is /src/utils/useContentfulClient.ts.
  2. Paste the following code block:
useContentfulClient.ts
import { useMemo } from 'react';
import { createClient } from 'contentful';

type Props = {
  isPreview?: boolean;
};

export const useContentfulClient = ({ isPreview }: Props) => {
  const client = useMemo(() => {
    const clientConfig = {
      space: process.env.GATSBY_CTFL_SPACE || '',
      environment: process.env.GATSBY_CTFL_ENVIRONMENT || '',
      host: 'cdn.contentful.com', // Alternatively can be 'preview.contentful.com' depending on your API preferences
      accessToken: isPreview
        ? process.env.GATSBY_CTFL_PREVIEW_ACCESS_TOKEN || ''
        : process.env.GATSBY_CTFL_ACCESS_TOKEN || '',
      experienceTypeId: process.env.GATSBY_CTFL_EXPERIENCE_TYPE || '',
    };
    return createClient(clientConfig);
  }, []);

  return { client };
};

Create the page component that a slug attaches to

  1. In the pages directory, create a directory named [locale] and then a file called [slug].tsx under the [locale] directory.
  2. Paste the following code block into [slug].tsx:
[slug].tsx
import {
  useFetchBySlug,
  ExperienceRoot,
} from '@contentful/experiences-sdk-react';
import { PageProps } from 'gatsby';
import React from 'react';
import { useContentfulClient } from '../../utils/useContentfulClient';

type PathParams = {
  locale: string;
  slug: string;
  isPreviewString: string;
};

const experienceTypeId = process.env.GATSBY_CTFL_EXPERIENCE_TYPE || '';

export default function StudioExperiencePage(pageProps: PageProps) {
  const { locale = 'en-US', slug = 'home-page' } =
    pageProps.params as PathParams;
  const isPreview =
    new URL(pageProps.location.href).searchParams.get('isPreview') === 'true';
  const { client } = useContentfulClient({ isPreview });

  const { experience, error, isLoading } = useFetchBySlug({
    slug,
    localeCode: locale,
    client,
    experienceTypeId,
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

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

Set up the environment variables

Create a file named env.development in the root directory of your project, at the same level as the gatsby-config.ts file. Paste the following code block into the file and set the appropriate values.

GATSBY_CTFL_ENVIRONMENT=
GATSBY_CTFL_SPACE=
GATSBY_CTFL_ACCESS_TOKEN=
GATSBY_CTFL_PREVIEW_ACCESS_TOKEN=
GATSBY_CTFL_EXPERIENCE_TYPE=
GATSBY_CTFL_DOMAIN=

The environment variables from the code block above are used by useContentfulClient.ts to fetch your experience entries.

Hook up the SDK to Experiences UI

Once you have completed all the steps above, follow these instructions to connect your Gatsby project to the Experiences UI and view it running locally:

  1. In the Contentful web app, create a new experience following the steps in Create an experience.
  2. Set up content preview. In the Contentful web app, set up a new content preview platform. Under the Preview URL area, select the Experiences toggle and set the Preview URL for Experiences to:
    http://localhost:8000/{entry.fields.slug}?isPreview=true
    This assumes that the Gatsby app runs on port 8000 by default. Make sure to set your preview setting to the created preview setting.
  3. Run your Gatsby project locally by running npm run develop.
  4. Refresh the Experiences UI and view your Gatsby app connected to Experiences.
  5. (Optional) Make changes and publish your experience. In the experience editor, click Open preview to see your experience live locally.

Set up static site generation

To set up static site generation, create a new page for each experience entry by using the createPages function in the gatsby-node.mjs file.

  1. If you don't already have one, create a file named gatsby-node.mjs in the root directory of your project.
  2. Paste the following code block into the file and update the code as needed for your application:
import { createClient } from 'contentful';
import {
  detachExperienceStyles,
  fetchBySlug,
} from '@contentful/experiences-sdk-react';
import path from 'path';

const isPreview = true;
const contentType = process.env.GATSBY_CTFL_EXPERIENCE_TYPE || '';
const localeCode = 'en-US';

const clientConfig = {
  space: process.env.GATSBY_CTFL_SPACE || '',
  environment: process.env.GATSBY_CTFL_ENVIRONMENT || '',
  host: isPreview ? 'preview.contentful.com' : 'cdn.contentful.com',
  accessToken: isPreview
    ? process.env.GATSBY_CTFL_PREVIEW_ACCESS_TOKEN || ''
    : process.env.GATSBY_CTFL_ACCESS_TOKEN || '',
  experienceTypeId: contentType,
};
const client = createClient(clientConfig);

export const createPages = async function ({ actions }) {
  // Fetch all experience entries using a Contentful client
  const entries = await client.getEntries({
    content_type: 'experienceLayout', // make sure you use the correct content type for your experiences
    select: ['fields.slug'],
  });

  // Loop through each entry and create a new page for each
  for (const item of entries.items) {
    try {
      const { slug } = item.fields || {};

      const experience = await fetchBySlug({
        client,
        slug,
        experienceTypeId: contentType,
        localeCode,
        isEditorMode: false,
      });
      if (!experience) {
        console.warn(`Experience not found for slug ${slug}`);
        return;
      }
      // Detach the styles from the experience so we can pass them to the page
      const stylesheet = detachExperienceStyles(experience);
      actions.createPage({
        path: slug,
        component: path.resolve(`./src/templates/ExperienceTemplate.tsx`),
        context: {
          experienceJson: JSON.stringify(experience),
          stylesheet,
          localeCode,
        },
      });
      console.log(`created page for slug ${slug}`);
    } catch (e) {
      console.warn('Error when fetching experience', e.message);
    }
  }
};

For an in-depth example of using Experiences with static site generation, refer to the Gatsby example.