Guide to Build Your First Simple App

In this section, we will learn how to build a simple “Color Picker” application using the Contentstack app framework. This will enable a custom field UI location in the stack, which provides a native color picker polyfill that Contentstack users can use as an input field within a content type.

This step-by-step guide explains how to create a Color Picker custom field app for your content types.

Prerequisites

  • Contentstack account with access to Developer Hub
  • Organization or stack admin access
  • Node.js version 12 or above
  • Understanding of App SDK
  • Understanding of React.js
  • Venus Component Library for designing UI

Overview of steps:

  1. Setup a New React Project
  2. Register the App
  3. Configure UI Locations
  4. Install the App
  5. Use Color Picker as a Custom Field
  6. Update App Code and Test
  7. Next steps
  1. Setup a New React Project

    1. The first step is to set up a new project that can be used as the app code in the app. You can either download the boilerplate or set up your project from scratch using the App SDK.
    2. Note: This guide is written assuming you are using boilerplates or a project with similar structure.

    3. Switch to the project directory from CLI:
      • Run the below command to install all modules:
      • $ npm install
        
      • Start the project:
      • $ npm run dev
        

    This hosts your application on http://localhost:3000. We can now use this URL to register the application.

  2. Register the App

    To register your app with Contentstack, log in to your Contentstack account and follow the steps given below:

    1. On the left navigation panel, you will find an icon for Developer Hub (as shown below). Click on the icon to go to the Developer Hub.
    2. 1.png
    3. Click on the + New App button.
    4. In the New App modal that appears, enter the following details:
      • Type of App (required): Select Stack App as we plan to create a custom field UI location within a stack.
      • Name (required): Enter the name of your application (for example, Sample App).
      • Description (optional): Enter a description for your app.
      • 2.png
    5. Click on the Create button.
    6. On the Basic Information screen, you can view the details about your app.
  3. Configure UI Locations

    In the configure UI locations section, you can add and configure UI locations for your application. Since we are creating a color picker custom field, we’ll add and configure the custom field UI location.

    1. On the left navigation panel, click on the UI Locations tab.
    2. 3.png
    3. Enter the App URL. This is the same URL, where your app is hosted. In this case, it is http://localhost:3000.
      4.png
      The App Location(s) section is enabled once you enter the App URL.
    4. Hover over the Custom Field UI Location, click on the + Add button.5.png

    5. Configure the Custom Field meta information.
    6. 6.png
      • Name (optional): By default, the app name is set as the custom field location name. Enter appropriate names for the location, when you have multiple fields of the same type.
      • Signed (required): When enabled, it will send a JWT token signed by signing keys from CONTENTSTACK_REGION_URL/.well-known/public-keys.json.
        This is useful when the app is shared with other organizations, and the app calls APIs that exchange data from the backend. For more information refer to the Signed Locations document.
      • Path (optional): The path mentioned is appended to the base app URL of the entry page consisting of the custom field location. Useful when the developer wants to load application code from the sub-URI of the app URL or the apps that may contain many UI locations to manage the code. For example, enter path as #/custom-field.
      • Data Type (required): You need to define what data type this custom field location is targeting. For example, select the data type Text.
      • Description (optional): Enter a suitable description for your custom field location. This description will be visible on the entry page when the user uses the custom field location.
      • Enabled (required): Allows you to disable it during the installation process and enable it via the configuration page.
    7. Click on Save to save your UI location details in the manifest.
    On saving, you will be directed to the UI Locations page. You will see that one location has been configured in the App Locations section. 7.png
  4. Install the App

    Now that you have configured your custom field location, you need to install the app. Installing the app will make it available in the specific stack you select.

    1. Click on Install App on the top right corner.
    2. 8.png
    3. Select the stack within which you want to install the Color Picker app. Check the terms of service checkbox and click Install.
    4. 9.png
    5. You will be redirected to the installed apps page in Marketplace, where you can see all the installed apps in your organization.
    6. Now that your app is installed in your stack, the custom field from boilerplate is ready to use.
  5. Use Color Picker as a Custom Field

    Your Color Picker app is now installed within your stack, but to use it you need to add it within your content type. Open the stack in which you have installed the Color Picker app and follow the steps given below:

    1. Click on the Content Models icon on the left navigation panel, and click on the + New Content Type button.
    2. Create a content type by adding relevant details as displayed below:
    3. 10.png
    4. In the Content Type Builder page, add the Custom field to your content type by clicking on the “Insert a field” link denoted by a + sign.
    5. 11.png
    6. Name your custom field and configure other properties of your custom field. Under Select Extension/App, select the Color Picker custom field that you created.
    7. 12.png
    8. After adding the fields, click on either Save or Save and Close to save your changes.

    To use the Color Picker app, create an entry for this content type, and you will see the this field on your entry page as shown below:

    13.png

    At this point, the code does not show the color picker app and should just show an error message. Now let's add the actual color picker code to the app.

  6. Update the Code and Test

    Now that you have installed the Color Picker app, you need to add the color picker code and update the boilerplate code to suit your application.

    1. Add the Color Picker type to the Type file in `/ui/src/common/types/index.tsx`
    2. export interface ColorPickerData {
          showPicker: boolean;
          pickerColor: {
              r: any;
              g: any;
              b: any;
              a: any;
          };
      }
    3. In the /ui/src/containers/CustomField/index.tsx file, replace the custom field code with the code given below:
    4. /* Import React modules */
      import React, { useEffect, useState } from "react";
      import { SketchPicker } from "react-color";
      import reactCSS from "reactcss";
      /* Import other node modules */
      import { InstructionText } from "@contentstack/venus-components";
      import ContentstackAppSdk from "@contentstack/app-sdk";
      /* Import our modules */
      import localeTexts from "../../common/locale/en-us";
      import { TypeSDKData, ColorPickerData } from "../../common/types";
      /* Import node module CSS */
      /* Import our CSS */
      import "./styles.scss";
      
      const CustomField: React.FC = function () {
          const [state, setState] = useState<TypeSDKData>({
              config: {},
              location: {},
              appSdkInitialized: false,
          });
      
          const [stateColor, setColor] = useState<ColorPickerData>({
              showPicker: false,
              pickerColor: {
                  r: "108",
                  g: "92",
                  b: "231",
                  a: "100",
              },
          });
      
          const styles = reactCSS({
              default: {
                  color: {
                      width: "70px",
                      height: "30px",
                      borderRadius: "4px",
                      background: `rgba(${stateColor.pickerColor.r}, ${stateColor.pickerColor.g}, ${stateColor.pickerColor.b}, ${stateColor.pickerColor.a})`,
                  },
              },
          });
      
          const togglePickerVisibility = () => {
              setColor((prev) => ({
                  showPicker: !prev.showPicker,
                  pickerColor: prev.pickerColor,
              }));
          };
      
          const closePicker = () => {
              setColor((prev) => ({
                  showPicker: false,
                  pickerColor: prev.pickerColor,
              }));
          };
      
          const pickerColorChanged = (colour: any) => {
              setColor((prev) => ({
                  showPicker: prev.showPicker,
                  pickerColor: colour.rgb,
              }));
              state.location?.CustomField?.field?.setData(colour);
          };
      
          useEffect(() => {
              ContentstackAppSdk.init().then(async (appSdk) => {
                  const config = await appSdk?.getConfig();
      
                  setState({
                      config,
                      location: appSdk.location,
                      appSdkInitialized: true,
                  });
      
                  appSdk.location.CustomField?.frame?.updateHeight?.(300);
      
                  const initialData = appSdk.location?.CustomField?.field?.getData();
      
                  if (initialData?.rgb) {
                      setColor({
                          showPicker: false,
                          pickerColor: initialData.rgb,
                      });
                  }
              });
          }, []);
      
          return (
              <div className="layout-container">
                  {state.appSdkInitialized && (
                      <div>
                          <InstructionText testId="color-picker-text">
                              {localeTexts.customField.instruction}
                          </InstructionText>
                          <div>
                              <div className="swatch" role="none" onClick={togglePickerVisibility} onKeyDown={togglePickerVisibility}>
                                  <div style={styles.color} />
                              </div>
                              {stateColor.showPicker ? (
                                  <div className="popover">
                                      <div className="cover" role="presentation" onClick={closePicker} onKeyDown={closePicker}>
                                      <SketchPicker color={stateColor.pickerColor} onChange={pickerColorChanged}/>
                                  </div>
                                  </div>
                              ) : null}
                          </div>
                      </div>
                  )}
              </div>
          );
      };
      
      export default CustomField;
      
    5. In the /ui/src/containers/customField/style.scss file, replace custom field CSS with the code given below:
    6. .config-wrapper {
          .Form__item {
              width: 500px;
          }
          .tippy-wrapper {
              margin-right: 10px;
          }
      
          .radio-wrapper {
              padding: 20px 10px;
          }
      
          .radio-button {
              margin-right: 20px;
          }
      
          .toggle-save-response {
              padding: 20px 10px;
          }
       }
      
      .swatch {
          padding: 5px;
          background: #fff;
          border-radius: 1px;
       } 
    7. Add new strings to locale to customField node in locales in `/ui/src/common/locale/en-us/index.ts`
    8. instruction: "Pick a Color",
    9. In package.json, add the additional libraries used above:
    10. $ npm install reactcss react-color
      $ npm i --save-dev @types/react-color
      
    11. Stop and restart your React project:
    12. $ npm run dev
      
    13. Reload the entry page and now you will see an actual Color Picker loaded into the custom field.
    14. 14.png
    15. Save any color and reload, and verify if the app is saving data and fetching it on reload.
  7. Next Steps

    1. Secure your application:
      Using the signed support, you can learn how to secure calls to outgoing APIs from the Contentstack UI and backend using the Contentstack App Framework.
    2. Host the app:
      The Contentstack App Framework allows you to host your app on Contentstack. Check out how to deploy your code to Contentstack and use it in the app.
    3. Submit for publishing:
      Once your application is production-ready and you want to share your solution with Contentstack Marketplace, you can check the App Submission and Approval Guide.

Was this article helpful?

Thanks for your feedbackSmile-icon

On This Page

^