Last updated Feb 28, 2023

Rate this page:

Build a custom UI app in Jira

Tunneling with custom UI apps is only supported on Chrome and Firefox browsers.

This tutorial walks you through creating a Forge app that displays custom UI content in a Jira issue. Using custom UI, you can define your own user interface using static resources, such as HTML, CSS, JavaScript, and images. The Forge platform hosts your static resources, enabling your app to display custom UI on Atlassian products. Custom UI apps inherit modern security features to ensure high trust between Atlassian, developers, and users.

At the end of this tutorial, you’ll have created a Forge app in Jira that uses custom UI to display customized UI content.

Forge provides multiple environments where you can deploy the app. This tutorial uses the CLI default, the development environment. See Environments and versions to learn more.

Before you begin

This tutorial assumes you're already familiar with developing on Forge. If this is your first time using Forge, see Getting started for step-by-step instructions on setting up Forge.

To complete this tutorial, you need the following:

Forge apps can't be viewed by anonymous users. To use a Forge app, you must be logged in to Jira.

Create your app

This app displays custom content in the issue panel of a Jira issue using custom UI.

  1. Navigate to the directory where you want to create the app. A new directory with the app’s name will be created there.

  2. Create your app by running:

    forge create
  3. Enter a name for your app. For example, hello-world-custom-ui.

  4. Select the Custom UI category.

  5. Select the jira-issue-panel template.

  6. Change to the app subdirectory to see the app files.

    cd hello-world-custom-ui

Jira issue panel custom UI template

The jira-issue-panel-custom-ui template has React JS for the static frontend and Node JS for the FaaS backend. The template contains the following structure:

|-- src
|   `-- index.js
|-- static
|   `-- hello-world
|       `-- src
|           `-- index.js
|           `-- App.js
|       `-- public
|           `-- index.html
|       `-- package.json
|       `-- package-lock.json
|-- manifest.yml
|-- package.json
|-- package-lock.json

Let’s have a look at what these files are:

Change the panel title

This app displays content in a Jira issue panel using the jira:issuePanel module. Jira shows the title of the jira:issuePanel as the panel's heading. Let's change the title to include your name.

  1. In the app’s top-level directory, open the manifest.yml file.
  2. Find the title entry under the jira:issuePanel module.
  3. Change the value of title from hello-world-custom-ui to Hello World from <your name>. For example, Hello World from Emma Richards.

Your manifest.yml file should look like the following, with your values for the title and app ID.

    - key: hello-world-panel
      resource: main
        function: resolver
      viewportSize: medium
      title: Hello World from Emma Richards
    - key: resolver
      handler: index.handler
  - key: main
    path: static/hello-world/build
  id: '<your app id>'

Build the content for your custom UI

In this template, we're using create-react-app to generate the static content that your app will be using. This library is generally used to create new single-page React applications. We'll use the library to generate a simple Hello, world! message in a Jira issue panel by serving a single-page React app.

You need to install and build these resources so your app can use them. Follow these steps to build the resources for your app:

  1. Navigate to the static/hello-world directory.

  2. Install the needed dependencies:

    npm install
  3. Build the assets:

    npm run build
  4. Navigate back to the top-level directory of your app.

Deploy and install your app

Any time you make changes to your app code, rebuild the static frontend as prescribed above and then run a deploy using the forge deploy command. This command compiles your FaaS code, and deploys your functions and static assets to the Atlassian cloud.

To install your app on a new site, run the forge install command. Once the app is installed on a site, it will automatically pick up all minor app deployments, which means you don't need to run the install command again. A minor deployment includes any change that doesn't modify app permissions in the manifest.

  1. Navigate to the app's top-level directory and deploy your app by running:

    forge deploy
  2. Install your app by running:

    forge install
  3. Select your Atlassian product using the arrow keys and press the enter key.

  4. Enter the URL for your development site. For example, View a list of your active sites at Atlassian administration.

Once the successful installation message appears, your app is installed and ready to use on the specified site. You can always delete your app from the site by running the forge uninstall command.

Running the forge install command only installs your app onto the selected product. To install onto multiple products, repeat these steps again, selecting another product each time. Note that the Atlassian Marketplace does not support cross-product apps yet.

You must run forge deploy before running forge install in any of the Forge environments.

View your app

With your app installed, it’s time to see the app on an issue.

  1. Create a new Jira issue.
  2. View the issue you created.

The app should display on the page with the content of your custom UI, like the image below.

A Jira issue displaying a custom UI forge app

While your app is deployed to either a development or staging environment, (DEVELOPMENT) or (STAGING) will appear in your app title. This suffix is removed once you've deployed your app to production.

Modify the content of your custom UI

By now, you can now see your app displaying the message Hello World from <your name> in the Jira issue panel. This is the product of setting up your static assets & using a resolver function to dynamically generate the message.

Modify the static assets for the frontend

Follow these steps to modify the static assets:

  1. Navigate to the static/hello-world/src directory.

  2. Open the App.js file. The default content of the file is shown below.

    import React, { useEffect, useState } from 'react';
    import { invoke } from '@forge/bridge';
    function App() {
      const [data, setData] = useState(null);
      useEffect(() => {
        invoke('getText', { example: 'my-invoke-variable' }).then(setData);
      }, []);
      return (
          {data ? data : 'Loading...'}
    export default App;
  3. Modify the content of the file.

  4. Rebuild the static assets for your custom UI frontend by running the npm run build command from the static/hello-world directory.

  5. Navigate to the app's top-level directory and start a tunnel for your app by running:

    forge tunnel

    You can see your changes by refreshing the page that your app is on.

    You have to create a resources definition for this to work. This is described under Connecting the tunnel to your own dev server on the Tunneling page.

  6. Redeploy your app by running the forge deploy command.

Modify the FaaS backend resolver

Follow these steps to modify the value of the message returned by your FaaS backend resolver:

  1. Navigate to the src directory.

  2. Open the index.js file. The default content of the file is shown below.

    import Resolver from '@forge/resolver';
    const resolver = new Resolver();
    resolver.define('getText', (req) => {
      return 'Hello, world!';
    export const handler = resolver.getDefinitions();
  3. Modify the content of the file.

  4. Navigate to the app's top-level directory and start a tunnel for your app by running:

    forge tunnel

    You can see your changes by refreshing the page that your app is on.

    You have to create a resource definition for this work. This is described under Connecting the tunnel to your own dev server on the Tunneling page.

  5. Redeploy your app by running the forge deploy command.

Next steps

You now know enough to develop your own Forge apps. Continue on to our tutorials, explore the example apps, or look through the reference pages to learn more.

Rate this page: