cs-icon.svg

Set up Live Preview with GraphQL for Client-side Rendering (CSR)

Live Preview for GraphQL allows you to preview data in real-time with the help of GraphQL APIs. This guide provides a comprehensive walkthrough on how to configure Live Preview with GraphQL for a Client-side Rendering (CSR) website.

Prerequisites

Steps for Execution

Here is an overview of the steps involved in setting up Live Preview with GraphQL for your Client-side Rendering (CSR) sites:

  1. Set up the Website
  2. Host the Website
  3. Update Stack Settings
  4. Live Edit Tags for Entries (optional)

Set up the Website

These steps will guide you through configuring your website's code to enable the Live Preview functionality.

  1. Generate a preview token for configuration

    You can create a preview token within the Contentstack app by navigating to Settings > Tokens > Delivery Tokens (press “alt + O” for Windows or “option key + O” for Mac). 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. Therefore, if a delivery token doesn't exist, you must create a new one, where you can enable the Create Preview Token toggle. For an existing delivery token, you will find an option to generate a preview token. Click + Create Preview Token and copy the resulting token.

    Create-a-Preview-Token_GIF.gif
  2. Install and initialize the Live Preview utils SDK

    The Live Preview Utils SDK operates by monitoring content updates and instructing Contentstack's delivery SDK to retrieve draft or preview content or manage real-time content changes. To achieve this functionality, you must run this SDK on the client side.

    You can install Live Preview Utils SDK using two methods:

    Via npm:

    You can install the Live Preview Utils SDK package via npm by running the following command:

    npm install @contentstack/live-preview-utils
    

    You can now proceed to initialize the Live Preview Utils SDK by utilizing the init() method. This action establishes event listeners that monitor any modifications made to the content of the currently previewed entry.

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

    Note: To avoid configuration reset errors in your Live Preview setup due to rerendering, it's crucial to encapsulate your Live Preview Utils SDK initialization code within a separate JavaScript file.

    Via script:

    To import and initialize the Live Preview Utils SDK using the script tag of the HTML file, run the following code:

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

    To ensure the proper functioning of the website within the Live Preview panel, it's necessary to change the GraphQL API’s hostname. When the website operates within the Live Preview panel, the Live Preview SDK receives a hash in CSR mode. Consequently, you can examine this hash to switch to the appropriate hostname.

    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;
    }
    const gqlRequest = async (gql) => {
    const headers = getHeaders();
    const res = await fetch(graphqlUrl.toString(), {
    method: "POST",
    headers: headers,
    body: JSON.stringify({ query: gql }),
    });
    return res;
    };
    

    Here, a simple configuration is established. You have set up the graphqlUrl, which directs to the GraphQL endpoint, and created a getHeaders() function to supply the necessary headers and the gqlRequest() function is responsible for retrieving the data.

    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;
    }
    const gqlRequest = async (gql) => {
    const hash = ContentstackLivePreview.hash;
    const headers = getHeaders();
    if (hash) {
    headers.append("live_preview", hash);
    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, you can use ContentstackLivePreview.hash to selectively modify the hostname and headers. When it comes to enabling Live Preview, it's essential to transmit both the hash and preview_token. Once you have configured this data, you can continue using GraphQL just as you normally would.

    Note: For configuring the host parameter based on your specific regions, refer to the Base URLs for Live Preview section in the GraphQL API documentation.

    To fetch content in the live preview panel, it is recommended to utilize the preview token instead of the read-only management token. For additional details, please refer to the documentation on Preview tokens.

  4. Configure Live Preview across each webpage

    When you update an entry, the onEntryChange() method is triggered, allowing you to define any code logic for fetching data within this method.

    Each page contains a function responsible for fetching data and updating the state. In this example, React.js is used for illustration purposes. An updateData() function is created that is specifically designed to fetch data and update the React state.

    Now, within the useEffect() function, you can pass the updateData() function to the onEntryChange() method. This onEntryChange() method effectively runs the updateData() function every time you update the entry's content.

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

Host the Website

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

Update Stack Settings

To enable Live Preview through the stack settings in Contentstack, follow the steps given below:

  1. Go to Settings.
  2. Create a new environment if there are no existing environments in your stack.
  3. Add your hosted website URL as the base URL for the environment created.Add_Base_URL
  4. Navigate to the Live Preview section under stack's "Settings".
  5. Select the Enable Live Preview checkbox.
  6. Select the Default Preview Environment from the dropdown. This helps avoid having to add the preview settings manually across multiple entries.
  7. Save the settings.
    Live_Preview_Settings_in_Stack.png

You will now be able to see the Live Preview icon within all the entries of your stack and the feature will preview data from the hosted website.

Note: Since the preview service operates with draft data that hasn't been published, it cannot provide publish_details in its response.

Live Edit Tags for Entries (optional)

Live edit tags allow you to navigate to the field that contains the website content being previewed within the Live Preview pane. When you click on the "Edit" button beside a content block in the preview pane, you will be redirected to the corresponding field within the entry. If the field holds reference to another entry, you will be redirected to the referenced entry's editor page.

track_and_edit_in_live_preview_panel

Edit tags contain the location where the corresponding field lies within the entry. The Live Preview Utils SDK searches for the elements which contain the edit tags referred to as data-cslp.

The structure of the edit tag (field location in the entry) you can pass against the data-cslp attribute is as follows:

{content_type_uid}.{entry_uid}.{locale}.{field_uid}

Here's a sample field path:

home.blt80654132ff521260.en-us.modular_blocks.block_1.media_group_uid.image_uid

Note: If the field is nested within another complex field, such as Modular Blocks, provide the field path as follows: {modular_block_field_UID}.{block_UID}.{field_UID}.

For a website built using Contentstack's JavaScript Delivery SDK, you can use the addEditableTags() method to automatically generate the edit tag for you. The following section explains how you can set up live edit tags using addEditableTags().

Set Up Live Editing Using the addEditableTags Method

  1. Process entry for live editing

    Locate the section of your website's code responsible for fetching content from Contentstack. To ensure proper functionality of live editing, it's crucial to retrieve system {uid} from GraphQL at the root of the query and system {uid, content_type_uid} for all references.

    Here is an example of the gqlRequest() method for your reference:

    const query = `
      query HeaderQuery {
        all_header {
          items {
              page_Connection {
               edges {
                 node {
                   ... on Page {
                     title
                     system {
                       uid
                       content_type_uid
                     }
                   }
                 }
               }
             }
          system {
            uid
          }
        }
      }
    }
    let entry = await gqlRequest(query)
    

    Next, include _content_type_uid and uid alongside system, and assign the values from system.content_type_uid to _content_type_uid and system.uid to uid. As a result, the final output will appear as follows:

    {
      "all_header": {
        "items": [
          {
            "page_referenceConnection": {
              "totalCount": 1,
              "edges": [
                {
                  "node": {
                    "title": "Home",
                    "url": "/",
                    "uid": "blt336e63b68a71c1cb",
                    "_content_type_uid": "page",
                    "system": {
                      "uid": "blt336e63b68a71c1cb",
                      "content_type_uid": "page"
                    }
                  }
                }
              ]
            },
            "system": {
              "uid": "bltf9961a71ea3fd917"
            },
            "uid": "bltf9961a71ea3fd917"
          }
        ]
      }
    }
    
  2. Import the addEditableTags() method

    Install Contentstack Utils from npm using the following command:

    npm i @contentstack/utils
    

    After obtaining your data, make sure to import the addEditableTags() method from the Contentstack SDK.

    import {addEditableTags} from "@contentstack/utils”
    
  3. Generate edit tags for previewed entry content

    After retrieving data from Contentstack, pass the resultant entry within the addEditableTags() function to add edit tags to the previewed entry content:

    addEditableTags(entry, content_type_uid, tagsAsObject, locale)
    

    Here, entry is the actual entry you get from the SDK, content_type_uid is the unique ID of the current entry’s content type, and tagsAsObject determines the format in which the edit tag would be added.

    Note: The addEditableTags() method does not return any value. It only modifies the entry passed as the first argument to the method.

    By default, tagsAsObject is set to false, and it appends data-cslp in the form of a string as follows:

    'data-cslp=path.to.field'
    

    Note: This option is provided for React-based apps as you cannot directly add any attributes in string format. Instead, you need to destructure an object.

    If tagsAsObject is set to true, the data-cslp attribute is returned in object format as follows:

    { 'data-cslp': 'path.to.field'}
    

    Here's a sample that shows how the code would look once you add the addEditableTags() method:

    let entry = gqlRequest(request)
    addEditableTags(entry[0][0], "content_type_uid", false)
    

    When you use the addEditableTags() method, a new key-value pair is returned at every level in the existing entry schema. This pair is known as the edit tag and is denoted by a dollar sign ($).

    For example, consider that you passed the following entry schema against the first parameter in the addEditableTags() method:

    {
        "name": "John Doe",
        "description": {
            "occupation": [{
                "name": "Plumber",
                "since": 1920
            }],
            "height": "5ft"
        }
    }
    

    Once the addEditableTags() method is executed, the entry passed against the first parameter is updated as follows:

    {
        "name": "John Doe",
        "$": {
            "name": "profile.blt8tvsk328dbw258.en-us.name"
        },
        "description": {
            "$": {
                "occupation": "profile.blt8tvsk328dbw258.en-us.description.occupation",
                "height": "profile.blt8tvsk328dbw258.en-us.description.height"
            },
            "occupation": [{
                "$": {
                    "name": "profile.blt8tvsk328dbw258.en-us.description.occupation.name",
                    "since": "profile.blt8tvsk328dbw258.en-us.description.occupation.since"
                },
                "name": "Plumber",
                "since": 1920
            }],
            "height": "5ft"
        }
    }
    
  4. Set up the Live Preview Utils SDK

    Live Preview requires the stack API key and host URL to perform appropriate redirection to the relevant stack.

    ContentstackLivePreview.init({
        ...
        stackDetails: {
           apiKey: "your api key",
           environment: "your environment",
           branch: "your branch"
    },   clientUrlParams: {
                  host: "app.contentstack.com",
       },
    })
    

    Here, the clientUrlParams key is optional and is set for the North America region.

    For other Europe region, you can use the following configurations for clientUrlParams:.

    {
       host: "eu-app.contentstack.com"
    }
    

    For Azure NA region, use the following config:

    {
       host: "azure-na-app.contentstack.com"
    }
    

    For Azure EU region, use the following config:

    {
       host: "azure-eu-app.contentstack.com"
    }
    
  5. Configure live edit tags for each webpage

    Now, navigate to the section in your website's front-end HTML code where you need to pass the edit tags as attributes. To access an edit tag, fetch the path to a field in the entry and add a dollar sign ($) before the last field in the field depth hierarchy.

    For example, if the path to your entry data is data.description.height, then the corresponding edit tag will be data.description.$.height.

    Once you add the edit tag, content managers will be able to see the "Edit" icon whenever they hover over the corresponding content block on the website.

    <header class="text-center">
        <div class="author">
            <img {{ data.author.profile_image.$.url }} src="{{ data.author.profile_image.url }}" alt="{{ data.author.title }}"/>
        </div>
        <h1 {{ data.author.$.title }}>{{ data.author.title }}</h1>
        <h2 class="author-job" {{ data.author.$.job_title }}>{{ data.author.job_title }}</h2>
        <p class="author-bio" {{ data.author.$.biography }}>{{ data.author.biography }}</p>
        <div class="author-social">
            <a href="mailto:{{ data.author.social.email }}"><ion-icon name="mail-outline"></ion-icon></a>
            <a href="https://www.twitter.com/{{ data.author.social.twitter }}"><ion-icon name="logo-twitter"></ion-icon></a>
            <a href="https://www.instagram.com/{{ data.author.social.instagram }}"><ion-icon name="logo-instagram"></ion-icon></a>
        </div>
    </header>
    

    For React-based applications, you can generate edit tags by setting the tagsAsObject parameter to true. When set to true, this parameter returns the edit tag in object format. You need to destructure the object while passing it within the JSX element.

    Here is an example of an edit tag that is returned in object format:

    <h1 {...data.$.name}>{data.name}</h1>
    <p> {...data.description.$.height}>{data.description.height}</p>
    

    Note: This setup only works for generic websites that use basic JavaScript frontend code. For websites working on other programming languages, you need to provide the entire path to the specific field.

  6. Add CSS to display edit buttons in the project

    Note: This step is not required for Live Preview SDK version 2.0.0 and above.

    The styles for the live edit tags are available in the @contentstack/live-preview-utils/dist/main.css file. You can import these styles in your Gatsby pages or your layout components as follows:

    import "@contentstack/live-preview-utils/dist/main.css";
    

    Alternatively, you can directly import the CSS within the HTML using the following code:

    <link rel="stylesheet" href="https://unpkg.com/@contentstack/live-preview-utils@1.4.3/dist/main.css">
    

Once you have configured the settings, you will be able to see the Edit icon whenever you hover over a content block in your preview panel.

edit_icon_in_the_live_preview_panel
Was this article helpful?
^