cs-icon.svg

Set Up Live Preview with GraphQL for CSR

Use GraphQL APIs to preview content in real time with Live Preview. This guide explains how to configure Live Preview with GraphQL for a Client-side Rendering (CSR) website.

Prerequisites

Follow these steps to configure Live Preview with GraphQL for your CSR website:

  1. Set Up the Website

    To enable Live Preview on your website, begin by setting up the essentials—create a preview token, install the Live Preview Utils SDK, and configure your GraphQL requests to support real-time updates.

    1. Generate a Preview Token

      Create a preview token by navigating to Settings > Tokens > Delivery Tokens (press “Alt + O” for Windows or “Option + O” for Mac).

      Note: It is recommended to use a preview token for Live Preview instead of a previously utilized, read-only management token.

      Each preview token is associated with a delivery token and shares access to the specific environment. If a delivery token doesn't exist, create one and enable the Create Preview Token toggle. For an existing delivery token, use the + Create Preview Token option and copy the generated token.

      alt_text
    2. Install and Initialize Live Preview Utils SDK

      Use the Live Preview Utils SDK to listen for content updates and fetch real-time preview data on the client side.

      Install the SDK using one of the following methods:

      1. Via npm:

        Install the Live Preview Utils SDK package via npm by running the following command:

        npm install @contentstack/live-preview-utils@contentstack/utils

        Initialize the SDK using the init() method to set up event listeners for content updates:

        import ContentstackLivePreview from "@contentstack/live-preview-utils";
        ContentstackLivePreview.init({ ssr: false, enable: true });

        Note: To avoid configuration reset errors due to rerendering, place the initialization code in a separate JavaScript file.

      2. Via script:

        Install the SDK using a script tag in your HTML:

        <script type='module'>
          import ContentstackLivePreview from 'https://esm.sh/@contentstack/live-preview-utils@3.0.1';
          ContentstackLivePreview.init({
            enable: true,
            ssr: false,
            stackDetails: {
              apiKey: "your-stack-api-key",
            },
          });
        </script>
    3. Update the GraphQL URL and Headers

      To enable Live Preview in the preview panel, update the GraphQL API’s hostname dynamically based on the presence of a hash.

      Example: Basic configuration for GraphQL requests

      //utils.js
      const graphqlUrl = new URL(
        `https://graphql.contentstack.com/stacks/${REACT_APP_CONTENTSTACK_API_KEY}?environment=${REACT_APP_CONTENTSTACK_ENVIRONMENT}`
      );
      
      function getHeaders() {
        const headers = new Headers();
        headers.append("Content-Type", "application/json");
        headers.append("access_token", REACT_APP_CONTENTSTACK_DELIVERY_TOKEN);
        return headers;
      }
      
      export const gqlRequest = async (gql) => {
        const headers = getHeaders();
        const res = await fetch(graphqlUrl.toString(), {
          method: "POST",
          headers: headers,
          body: JSON.stringify({ query: gql }),
        });
        return res;
      };

      This example configures the GraphQL endpoint and defines the getHeaders() function to provide the required headers. The gqlRequest() function retrieves data from Contentstack’s GraphQL API.

      Example: Conditional configuration for Live Preview

      //utils.js
      import ContentstackLivePreview from "@contentstack/live-preview-utils";
      
      const graphqlUrl = new URL(
        `https://graphql.contentstack.com/stacks/${REACT_APP_CONTENTSTACK_API_KEY}?environment=${REACT_APP_CONTENTSTACK_ENVIRONMENT}`
      );
      
      const GRAPHQL_HOST_NAME = "graphql.contentstack.com";
      const LIVE_PREVIEW_HOST_NAME = "graphql-preview.contentstack.com";
      
      function getHeaders() {
        const headers = new Headers();
        headers.append("Content-Type", "application/json");
        headers.append("access_token", REACT_APP_CONTENTSTACK_DELIVERY_TOKEN);
        return headers;
      }
      
      export const gqlRequest = async (gql) => {
        const hash = ContentstackLivePreview.hash;
        const headers = getHeaders();
      
        if (hash) {
          headers.append("live_preview", hash);
          headers.append("include_applied_variants", "true");
          headers.append("preview_token", REACT_APP_CONTENTSTACK_PREVIEW_TOKEN);
          graphqlUrl.hostname = LIVE_PREVIEW_HOST_NAME;
        } else {
          graphqlUrl.hostname = GRAPHQL_HOST_NAME;
        }
      
        const res = await fetch(graphqlUrl.toString(), {
          method: "POST",
          headers: headers,
          body: JSON.stringify({ query: gql }),
        });
      
        return res;
      };

      In this example, ContentstackLivePreview.hash detects when the website runs inside the preview panel. When this value is present, it switches the hostname and adds both the live_preview and preview_token headers to enable Live Preview.

      Note: Always use a preview token for Live Preview instead of a read-only management token. For region-specific hostnames, refer to the Base URLs for Live Preview section.

    4. Configure Live Preview across Each Webpage

      When you update an entry, the onEntryChange() method detects the change and runs your defined logic to fetch updated data. In a React-based setup, each page typically includes a function that retrieves data and updates the component state.

      In the example below, an updateData() function handles the data fetch and state update. Pass this function to onEntryChange() inside a useEffect() hook to automatically refresh the data whenever the entry content changes.

      // Blog.js
      import React from "react";
      import ContentstackLivePreview from "@contentstack/live-preview-utils";
      
      import { gqlRequest } from “./utils.jsconst Footer = () => {
          const query = `
              query MyQuery {
              all_page(where: {url: "/blog"}) {
                 items{ 
                 title
                  seo {
                      enable_search_indexing
                      keywords
                      meta_description
                      meta_title
                  }
              }
            }
          }
          `;
      
          const [data, setData] = React.useState({});
      
          const updateData = async () => {
      const fetchedData = await gqlRequest(query);
      setData(fetchedData);
      };
      
          React.useEffect(() => {
             ContentstackLivePreview.onEntryChange(updateData);
          }, []);
      
          return <div>{data.all_page.items[0].title;
      };
  2. Host the Website

    To host a website, you can simply use launch or any other website hosting service.

  3. Update Stack Settings

    To set up Live Preview for the entries of your stack, perform the following steps:

    1. Navigate to Settings and select Environments.
    2. Set the base URLs for different locales, and click Save. alt_text
    3. Navigate to Live Preview in the left navigation panel and select the Enable Live Preview checkbox.
    4. Set the Default Preview Environment and click Save to save the settings.

      Tip: You can also update the preview URL and environment from the preview settings available on the entry page.

      alt_text

    You can now see the Live Preview icon within all the entries of your stack. The feature previews data from the hosted website in real time.

  4. Live Edit Tags for Entries (optional)

    Live Edit tags allow editors to jump directly from the Live Preview pane to the relevant content fields in the entry editor. Clicking the Edit button opens the appropriate field. If the field references another entry, the editor is redirected accordingly.

    Additional Resource: For more details, refer to our Set Up Live Edit Tags for Entries with REST documentation.

Was this article helpful?
^