Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. Retrieve Contentful API keys from the UI.

    1. Code Block
      CONTENTFUL_SPACE_ID="YOUR_SPACE_ID"
      CONTENTFUL_ACCESS_TOKEN="YOUR_CONTENTFUL_CONTENT_DELIVERY_API_KEY"

    2. Implement the API Keys in project.

    3. This code sample shows the connection to Contentful’s GraphQL API, and how we can access the our space by providing those API keys.

      1. Code Block
        languagejs
        async function fetchGraphQL(query, preview = false) {
          return fetch(
            `https://graphql.contentful.com/content/v1/spaces/${process.env.CONTENTFUL_SPACE_ID}`,
            {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${
                  preview
                    ? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN
                    : process.env.CONTENTFUL_ACCESS_TOKEN
                }`,
              },
              body: JSON.stringify({ query }),
            }
          ).then((response) => response.json());
        }

    4. Once we have a GraphQL connection to Contentful, we can access various entries by querying that source.

      1. Code Block
        //Example GraphQL Query for Post types
        
        export async function getAllPostsForHome(preview) {
          const entries = await fetchGraphQL(
            `query {
              postCollection(order: date_DESC, preview: ${preview ? "true" : "false"}) {
                items {
                  ${POST_GRAPHQL_FIELDS}
                }
              }
            }`,
            preview
          );
          return extractPostEntries(entries);
        }

    5. After we grab what content we need, we can then render the payload to the page.

      1. Example of a ReactJS/NextJS component that has a connection to Contentful

      2. Code Block
        import Error from "next/error";
        import { useRouter } from "next/router";
        import React, { useMemo } from "react";
        import Container from "../../components/container";
        import ContentfulImage from "../../components/contentful-image";
        import Layout from "../../components/layout";
        import SideCard from "../../components/side-card";
        import useBsftEvent from "../../custom-hooks/useBsftEvent";
        import { PublicationCardData } from "../../data/PublicationData";
        import {
          getNavigation,
          getPublicationBySlug,
          getPublicationsWithSlug,
        } from "../../lib/api";
        import { NavType } from "../../redux/reducers/layout.reducer";
        import { Publication } from "../../types/publications";
        
        const Publication = ({
          pub,
          navItems,
        }: {
          pub: Publication;
          navItems: Array<NavType>;
        }) => {
          const router = useRouter();
        
          const bsftEvent = useBsftEvent({
            eventType: "view",
            data: pub,
            params: {
              sku: pub?.sys?.id,
              category_id: "PUBLICATION/ITEM",
              title: pub?.title,
            },
          });
        
          if (!router.isFallback && !pub) {
            return <Error statusCode={404} />;
          }
        
          return (
            <Layout preview={false} navItems={navItems}>
              <Container>
                <div className="py-28 flex w-full justify-between gap-20">
                  <div className="w-2/3">
                    <div className="my-12">
                      <h4 className="font-semibold text-blue-300 text-xs">
                        {pub?.brand?.brand}
                      </h4>
                      <img src={pub?.logo?.url} className="max-w-md rounded my-4" />
                      <h1 className="text-slate-500 text-4xl font-bold my-8">
                        {pub?.title}
                      </h1>
                      <p className="text-slate-400 text-xl my-8">{pub?.description}</p>
                    </div>
        
                    <hr className="h-0.5 w-full bg-slate-300 block" />
                    <div className="my-10">
                      <h2 className="font-bold text-3xl text-slate-500">
                        Meet the editor
                      </h2>
                      <div className="my-10 flex items-center">
                        <ContentfulImage
                          classes="w-full object-cover object-center rounded-full"
                          src={pub?.guru?.headshot?.url}
                          height="100%"
                          width="100%"
                        />
                        <h2 className="ml-8 font-semibold text-2xl">
                          {pub?.guru?.name}
                        </h2>
                      </div>
                      <p className="text-slate-400 text-xl">{pub?.guru?.bio}</p>
                    </div>
                  </div>
                  <div className="w-1/3 my-12">
                    <SideCard content={PublicationCardData} />
                  </div>
                </div>
              </Container>
            </Layout>
          );
        };
        
        export async function getStaticProps({
          preview = false,
          params,
        }): Promise<{ props: { pub: any; navItems: Array<NavType> } }> {
          const pub = (await getPublicationBySlug(params.slug)) ?? null;
        
          const navItems = (await getNavigation()) ?? [];
          return {
            props: {
              pub,
              navItems,
            },
          };
        }
        
        export async function getStaticPaths(): Promise<{
          paths: Array<string>;
          fallback: boolean;
        }> {
          const pubs = (await getPublicationsWithSlug()) ?? [];
          return {
            paths: pubs?.map(({ slug }) => `/publications/${slug}`) ?? [],
            fallback: true,
          };
        }
        
        export default Publication;