Developing a Jira App: Getting Started with Atlassian Forge

Getting Started with Atlassian Forge

Forge is Atlassian’s next-generation framework for building apps that integrate with Confluence, Jira, or Jira Service Management. Forge provides Web UI elements, APIs and deployment environments that enable developers to create fully-featured apps within Atlassian’s cloud infrastructure through the use of JavaScript, HTML, CSS and other Web technologies. Forge apps can be distributed via the Atlassian Marketplace as software to which any Atlassian Cloud customer can subscribe.

Atlassian provides substantial documentation [1] for the various building blocks that you, as a developer, can employ to compose your Forge app. However, not all documentation is perfect, and there are usually gaps. This blog is intended to cover some of the gaps and help you get to a “Hello World” level.

Let's Go

First, follow the steps described on Forge’s Getting Started page [2], then come back to this blog. Also, we’ll be using Visual Studio Code as our development environment.

Now, from the terminal in Visual Studio Code, let’s use the forge create command to scaffold our app:

You’re presented with a couple of choices to make:

  • The name of the app. Let’s call it getting-started.

  • The app template category. You have multiple options; consult the Forge documentation for more information. In our case, we’ll choose Custom UI.

  • The app template. We’ll be creating a Jira project page [3] – that is, a Jira page that will display information associated with a given Jira project – so we’ll select jira-project-page.

After a few moments, a directory containing code for a basic Forge app will be created. Let’s take a look:

The code structure is like that of a Node app. If you look closely, however, you’ll note that there are two sets of code:

  • The static directory and its subdirectories contain the UI code. A user of the app will receive a bundle containing these files when he or she accesses the app via a Web browser.

  • The src directory contains code that will run in the Atlassian cloud and can perform back-end functions. Check out the Forge runtime [4] for more information.

You’ll also notice that the one subdirectory of static is named hello-world. That string is also used in several places in the code. We’ll change that later.

A Note about Forge Environments

Out of the box, Forge provides three cloud environments in which your app can run – development, staging, and production. The name of each environment is fairly self-explanatory, but to find out more about the purpose and usage of each, you can visit Environments and Versions [5]. We’ll be using the development environment for our purposes.

Building the App

Let’s go ahead and try to build the app. First, we need to build the front-end portion by running npm run build in the …/static/hello-world directory:

Why didn’t that work? That’s because we haven’t installed required npm packages, which include (among others) React. Forge app UIs are React-based, and the template is built using Create React App. [6]

Let’s install those packages then try again. You probably noticed from the code structure that both the front-end code and the back-end code require separate sets of npm packages, so we’ll need to run npm install for both:

That’s better.

Deployment

Now, let’s try to deploy the app as-is to our development environment:

The forge deploy command does the actual deployment to whichever Atlassian Cloud environment you specify. It goes through a couple steps, one of which is to run the forge lint command, a linter that verifies that the code is deployable to Atlassian Forge. You can run that command directly if you wish.

Why is it failing? It turns out that the code generated by the Forge app template has a bug. We can resolve the bug by moving the …/static/hello-world/public directory to …/static/hello-world/build, then running npm run build again for the front-end code:

Why did it fail this time? We just uncovered another bug. Namely, the react-scripts build that npm run build is running under the hood expects an index.html provided by Create React App that isn’t included in the code generated by the template. Download the file from https://github.com/facebook/create-react-app/blob/main/packages/cra-template/template/public/index.html, then create a …/static/hello-world/public directory and place it in there:

Now, let’s try to build and deploy again:

Excellent!

To run the deployed code, let’s visit the Atlassian Cloud developer site that you created as part of Forge’s Getting Started process in the Let’s Go section above. In the Jira section of that site – e.g., https://your-site.atlassian.net/jira/ – create a Jira project if you haven’t already, then visit the project’s page – e.g., https://your-site.atlassian.net/jira/software/c/projects/KEY – and look at the left-hand sidebar. You should see your app listed there:

Hmm… it isn’t. Why not? When a Forge app is deployed to a given environment, it’s made available to be installed for Atlassian Cloud sites. However, a further step is required to do the actual installation for a given site – the forge install command.

When you run that command, it will ask for the Atlassian site on which to install the app. Of course, you’ll enter the site you created while you followed the steps on Atlassian’s Getting Started page:

Let’s refresh the Jira page that we opened earlier:

Now you see the app’s name, a default icon, and an indication that the app is the development environment version. You may install development, staging and production versions of a given app on the same Atlassian instance.

Click on the app’s name. It’ll ask you to grant your Forge app certain permissions, called scopes. You can read more about scopes in Scopes for OAuth 2.0 (3LO) and Forge Apps [7]. This will become especially important once you perform certain operations such as calling Atlassian APIs. You’ll see the following:

When you click Allow Access, another page will open, listing the requested permissions and asking you to accept them. Once you do so, your app will run:

You briefly see a Loading… message, then Hello, world! appears. Success! You have a Forge app running in the Atlassian cloud!

Let’s Make a Back-End Change

Let’s change the message from Hello, world! to Hi, world! and then deploy the change. The message is generated by code in the back end’s index.js:

Reload the app in the browser, and…

Success! Our new message displays.

Let’s Make a Front-End Change

You’ll find that most of the code you write for your Forge app will be in the front end, no matter how simple the app. To start, though, let’s make a small change, run forge deploy and see what happens:

Now, reload the Forge app, and…

Why didn’t the change show up? It’s due to the fact that front-end changes require building before deployment. Let’s run npm run build in the front-end directory, and then deploy:

Refresh the app, and…

Success! Loading it… appeared, rather than Loading…

Running Locally via forge tunnel

Of course, you can run your code by building and then deploying every time you make a code change. However, it makes for a lot of waiting for deployment, and thus a slow develop-and-test cycle. Instead, you can tunnel, which enables you to run your code locally while attached to your Forge development environment. You can do tunneling by running forge tunnel in your app’s root directory:

Now, reload your app in your browser and watch what happens:

We see some messages scrolling past in the Visual Studio Code terminal. That means that the tunnel is running the local version of the app’s code, rather than the Atlassian cloud’s version thereof. Let’s see what happens when we make a local back-end code change, then reload the app in the browser:

Not bad! It hot-reloaded your back-end change.

That doesn’t help us with front-end changes, however. In that case, we need to stop the tunnel, do npm run build on the front-end code, then start the tunnel again. That’s not very efficient.

But wait, you can use Vite [8]! Vite is a Web development framework that enables effectively instant local compilation, hot module replacement and other features that shorten your dev cycle almost to nothing. To use Vite in your app, consult Robin Wieruch’s Migrate to Vite from Create React App tutorial [9], as well as Oliver Siebenmarck’s Development with Forge Tunnel and Vite video [10].

Making Atlassian API Calls from the Front End

Using the Forge Custom UI bridge [11], we have the ability to make Atlassian API calls from the front end. Let’s try it out by modifying our app to display a list of releases. First, add some releases (also called versions in Jira parlance) to your Jira project:

Then, change your front-end code’s App.js to look like so:

Since the Atlassian library calls are async, and to keep the example simple, I’m making the calls from within a useEffect() hook. I strongly recommend using TanStack Query [12] (formerly known as React Query) instead, not just for its support of async functions, but also for its general ability to structure your data access and mutation code in a modular way.

Now, do npm run build and forge deploy, as we’ve done before. What happens when we reload the app in the browser?

The word Releases appears, then disappears. What happened? Since our latest change involved the addition of an API call, let’s open up the browser’s developer console, then refresh the app. Notice one of the messages there:


That HTTP error code of 403 indicates that we don’t have permission to access that API. Why? Because we didn’t add the necessary security scope to make that call. Consult Atlassian’s documentation about the releases API [13], and notice the following:

In order to access the API, we’ll need to configure one of those scopes within our app. (I’ve always used the recommended, “classic” scope for a given API, but it might suit you better to use the granular scope in some cases.) To configure that scope, add the following section to the end of the app’s manifest.yml:

Since we made a front-end change, we’ll need to do npm run build as before. Then, run forge deploy:

Note the yellow text:

We've detected new scopes or egress URLs in your app.
Run forge install --upgrade and restart your tunnel to put them into effect.

So, let’s run that command, then follow the prompts:

Now, refresh the app in your browser. You’ll be prompted to accept the scope that was added, then the app will reload (it may require a second refresh in the browser):

Success! You now see a list of releases in the app.

That's it!

Development of apps in the Atlassian Forge framework is fairly simple. There are a couple of gotchas up front, but once you get past them, you’ll be developing feature-rich apps in no time. Enjoy!

References

Chris Low

Chris Low is a Senior Consultant at Moser Consulting. For over twenty years, he has designed and developed software of varying complexity and for various industries.

Previous
Previous

Developing a Jira App: Distributing Your Atlassian Forge App

Next
Next

Developing a Jira App: Design Consistency and Team Collaboration