In this tutorial, you'll use React to create a Zendesk Support app. To build the app, you'll use the Zendesk React app scaffold and Zendesk Garden React components. You can use the app's code as a starting point for your own app.

The app displays a timeline of events for a ticket requester. Agents can access the app while viewing a ticket in the Agent Workspace.

Disclaimer: Zendesk provides this article for instructional purposes only. Zendesk doesn't provide support for the app or example code in this tutorial. Zendesk doesn't support third-party technologies, such as React, Babel, or Webpack.

What you'll need

To complete this tutorial, you'll need the following:

Creating the app files

First, use the Zendesk React app scaffold to create starter files for an app named User events.

To create the app files

  1. In your computer's terminal, navigate to the folder where you want to store the app. Example:

    cd projects
  2. In the folder, run:

    zcli apps:new --scaffold=react
  3. At the prompts, enter the following values:

    • Directory name: user_events
    • Author's name: Your name
    • Author's email: Your email address
    • Author's website: Leave blank and press Enter.
    • App name: User events

    ZCLI creates the files for your project in the user_events folder. To learn more about the React app scaffold's file structure, see the documentation on GitHub.

Installing dependencies

The React app scaffold includes React, Webpack, and Zendesk Garden React component libraries as dependencies. Next, install the project's dependencies.

To install dependencies

  1. In your computer's terminal, navigate to the project's root folder. Example:

    cd projects/user_events
  2. In the project's root folder, run:

    npm install

    This command installs the dependencies listed in the project's package.json file.

Reviewing the project's source files

Browsers don't natively support JavaScript modules, such as those used to import React. Instead, React projects commonly use Webpack to convert code written with JavaScript modules, along with other assets, into browser-ready files.

The app scaffold uses Webpack to build Zendesk app files from source files in the src folder. When run, Webpack places the final app files in a dist folder in the project's root.

As part of the build, Webpack bundles any required JavaScript for the app into a single file. You can configure starting points for the bundle in the array of webpack.config.js. Your project uses src/javascripts/locations/ticket_sidebar.js as a starting point:

...module.exports = {  entry: {    app: [      ...      './src/javascripts/locations/ticket_sidebar.js',      ...    ]  },  ...}

The final bundled file includes any modules imported into ticket_sidebar.js using JavaScript's import or require keywords. Your project's ticket_sidebar.js file includes an import of the App module from src/javascripts/modules/app.js:

...import App from '../modules/app'
/* global ZAFClient */var client = ZAFClient.init()
client.on('app.registered', function (appData) {  return new App(client, appData)})

When the app loads, the code in ticket_sidebar.js creates a new instance of App. It passes the ZAF client and context data to the App instance. This lets you use the ZAF client in the App module's code. You can edit the App module in app.js to make changes to the Zendesk app.

Adding the timeline component

Next, update the App module to fetch the ticket requester's events. Use Zendesk Garden's Timeline component to display the events in the app.

To add the timeline component

  1. In the src/javascripts/modules folder, open app.js. Replace the file's contents with the following:

    import React from 'react'import { render } from 'react-dom'import { resizeContainer } from '../lib/helpers'import EventTimeline from './event_timeline'
    const MAX_HEIGHT = 1000
    class App {  constructor (client, appData) {    this._client = client    this._appData = appData    this.initializePromise = this.init()  }
      async init () {    const requesterId = (await this._client.get(''))['']    const eventRequestOptions = {      url: `/api/v2/users/${requesterId}/events`,      data: `page[size]=5`    }
        const events = (await this._client.request(eventRequestOptions))    // Sorts events by created_at timestamp    const sortedEvents =, b) => (a.created_at > b.created_at) ? 1 : -1)    const container = document.querySelector('.main')
        render(<EventTimeline events={sortedEvents} />, container)    return resizeContainer(this._client, MAX_HEIGHT)  }}
    export default App

    The code exports the App module as a class. When initialized, the class uses the ZAF client's get() method to fetch the ticket requester's user id. It then uses the id to make a request() call to the Get Zendesk User Events endpoint. The endpoint returns up to five events for the requester.

    To render the events, the class uses an EventTimeline component from a local event_timeline.js file. You'll create this component and file in the next step.

  2. In the src/javascripts/modules folder, create an event_timeline.js file. Paste the following into the file:

    import React from 'react'import styled from 'styled-components'import { ThemeProvider, DEFAULT_THEME } from '@zendeskgarden/react-theming'import { Timeline } from '@zendeskgarden/react-accordions'import { Span } from '@zendeskgarden/react-typography'import { toSentenceCase, formatDate } from '../lib/helpers'
    const StyledSpan = styled(Span).attrs({ isBold: true })`  display: block;  `
    export default function EventTimeline ({events}) {  return (    <ThemeProvider theme={{ ...DEFAULT_THEME }}>      <Timeline>        { => {          return (            <Timeline.Item key={} data-event-id={}>              <Timeline.Content>                <StyledSpan data-type='type'>{toSentenceCase(event.type)}</StyledSpan>                <Span hue='grey' data-type='date'>{formatDate(event.created_at)}</Span>              </Timeline.Content>            </Timeline.Item>          )        })}      </Timeline>    </ThemeProvider>  )}

    The file exports the EventTimeline component as a function. The function loops through the events returned by the Get Zendesk User Events request. It renders each event's type and created_at values using Zendesk Garden's Timeline component.

    The file also imports the toSentenceCase and formatDate functions to format event values. You'll create these functions in the next step.

  3. In the src/javascripts/lib folder, open helpers.js. Add the following toSentenceCase and formatDate functions to the bottom of the file:

    .../*** Helper to convert snake case strings to sentence case* @param {String} string Snake case string* @return {String} Sentence case string*/export function toSentenceCase (string) {  const finalString = string.replace(/_/g, ' ')  return finalString.charAt(0).toUpperCase() + finalString.slice(1)}
    /*** Helper to format ISO 8601 timestamps as human-readable datetime* @param {String} date ISO 8601 timestamp* @return {String} Formatted date. Example: Sep 1, 2099 2:55 PM*/export function formatDate (date) {  const formattedDate = new Date(date)  const options = {    year: 'numeric',    month: 'short',    day: 'numeric',    hour: 'numeric',    minute: 'numeric'  }  return formattedDate.toLocaleDateString('en-us', options)}

Running the app locally

Run your app locally to ensure it displays the Timeline component.

To run the app locally

  1. In the project's root folder, run:

    npm run watch

    The command uses Webpack to build and output the Zendesk app files to the dist folder. After the initial build, the command watches for changes to files in the src folder. If it detects a change, it automatically rebuilds the output files in dist.

    Note: To stop the command, press Ctrl+C.

  2. In another terminal session, run the following command in the project's root folder:

    npm run start

    The command starts a local ZCLI web server.

    Note: To stop the command, press Ctrl+C.

  3. In your browser's private or incognito window, sign in to Zendesk Support and go to the Agent Workspace. From the workspace, open a new or existing ticket.

    The URL should look like this:


  4. Append ?zcli_apps=true to the URL and press Enter. The URL should now look like this:


  5. Click the Apps icon.

  6. The app displays the event timeline.

Installing the app

As an optional step, you can upload and install the app as a private app in your Zendesk Support instance.

To install the app

  1. If running, stop the npm run watch and npm run start commands by pressing Ctrl+C in the respective terminal sessions.

  2. In the project's root folder, run:

    npm run build

    The command builds outputs the app files to the dist folder.

  3. In the project's root folder, run:

    zcli apps:create ./dist

    ZCLI packages, uploads, and installs the app to your Zendesk instance.

  4. In Admin Center, click the Apps and integrations icon () in the sidebar. Then select Apps > Zendesk Support apps.

    The app appears in the list of installed apps on the My Apps page.

Congratulations! You've created a Zendesk app that uses React. As a next step, you can get your app ready for production. Consider tackling the following tasks:

  • Adding error handling for the ZAF client's request() call

  • Limiting the Get Zendesk User Events request to specific event sources or times

  • Localizing the app's strings using the React app scaffold's i18n module

  • Updating the unit tests in the spec folder