I launched 20 Forge apps. Here's some feedback

This will probably be a rant but I recognize that things will improve over time.

I just launched 20 new simple Forge apps on the marketplace as a test of the platform. The platform is really not production ready for complex apps and has incredibly frustrating DX and end-user UX.

Went pure UI Kit because I knew Custom UI would be easier and more flexible to build in Connect. Also I wanted to jump in early on the MacroConfig sidebar which is currently exclusive to UI Kit.


  • Documentation and tutorials work. When I first started building Connect apps ~2-3 years ago the docs were so outdated that the hello world tutorial didn’t work.
  • The community forums are more active and have answers to questions (unlike Connect).
  • The CLI is cool and very easy to get started.
  • The app examples are good.



  • If you’re building any kind of macro with Forge, on first install it will show an “Allow Access” prompt. However this button is unclickable in the editor. Incredibly poor oversight.
  • Apparently this is set to be fixed in Q4 2022 (why so late?!).
  • To be honest it’s such a bad UX onboarding blocker that I wouldn’t recommend building any Forge macro app until this is fixed (2023 I guess).
  • Also see MacroConfig section below…


  • Prior to these simple 20 apps I tried to build a more complex voice-based app with Custom UI. The problem is the security lockdown on Forge is so intense that you’ll constantly hit a wall with the apps and packages you wish to use. eg if you want to use an npm package that happens to call window anywhere in that package, Forge will prevent it from running. There’s other simple JS that are blocked by Forge but you won’t find a list anywhere in the docs. Also if that package pulls a file from a CDN, you’ll need to manually include that CDN domain into your manifest file. It’s so painful it really isn’t worth using any external npm packages (which is 99.9% of dev these days).
  • I’m a solo dev so collaboration wasn’t an issue, but currently there is no clean way for multiple developers to work on the same app. Therein lies many of the downsides of Atlassian forcing developers to do use their server-side infrastructure for all developer environments. I currently manage 362 marketplace apps on Cloudflare’s infrastructure and it literally costs me $0 to host and $5/mth to serve millions of API calls per week. Once Atlassian lock developers into using Forge for all CI/CD and begin charging to use that service; I have no doubt it will be more expensive, slower and more cumbersome than what most devs currently use.
  • forge tunnel randomly crashes every 5-10min which requires a restart. It’ll also timeout with no warning other than a non-descript error message in the Confluence/Jira UI. I’d suggest the team switch out ngrok for Cloudflare Tunnel. All of my Connect apps have code splitting which is frustrating when using the inbuilt ngrok because there’s a low total request limit per 60 seconds.
  • Debugging is a nightmare since everything is running server-side on Atlassian’s infrastructure. So your console.log() will only display inside the terminal and the CLI will rarely throw useful error messages.


  • The storage limits are from the 1990s. I’d challenge anyone at Atlassian to attempt to build a polls or forms app on either Connect or Forge where all the data remains within the customer’s instance. Low storage limits encourage developers to store data externally which becomes a security issue. 32KB limit for a key-value is painfully restricting. That’s now been increased to 128KB on Forge (still 32KB on Connect). But for comparison, Cloudflare Workers KV have a 25MB limit. My workaround on both platforms is an elaborate set of functions to split data into 32KB or 128KB chunks and then loop to post/put/get data across multiple KVs (key:0, key:1, key:2 etc).

UI Kit:

  • UI Kit is severely limiting. At least with AtlasKit you’re using it with React and have access to full HTML. In UI Kit you cannot use HTML anywhere. I’m assuming the goal is to reach parity with the features of AtlasKit. But it’s also bizarre that the Atlassian developer ecosystem now has three siloed component kits which are all incompatible: AUI, AtlasKit, UI Kit.
  • Here’s one of many limiting hurdles: you cannot apply a href link to a button or image. Instead there’s a separate <Link/> component. Oh and that component has far less appearance options than <Button/>. Why wasn’t a href prop simply added?!
  • Another annoying one is the lack of standardization in regards to component props. eg <Button/> colors are danger, default, link, subtle, subtle-link, warning. <Badge/> colors are added, default, important, primary, removed. <Tag/> colors are green, blue, red, purple etc.
  • Also root level modules have non-standard component props. eg ContextMenu wants children, Macro does not: <ContextMenu><App></ContextMenu> versus <Macro app={<App/>}/>
  • Basic conditional code doesn’t work. Throughout my codebase I’ve had to write things like this because the normal way you’d write it doesn’t work:
  • Also found I had to declare default fallback values directly inside the props because if you set them higher up while deconstructing, it doesn’t work:


  • Oh boy. This was the primary exclusive UI Kit feature I wanted to use and it was a nightmare. For simple static apps where the config options never change, it’s passable. If you want to dynamically show/hide various form fields within <MacroConfig/> then you’re gonna have a bad time.
  • You’re not allowed to use <Button/> or <Text/> inside <MacroConfig/> so that rules out doing anything with complex config UI. So instead what I did was overkill it and use AI to map natural language into compatible UI Kit components. ie user types in “red button” and I render the config fields dynamically with <TextField name="color" defaultValue="red"/>. Subsequently this limitation became the general theme of all the Forge apps I built.
  • Problem is once you dynamically render MacroConfig form fields, there is no way to programmatically call the useConfig() hook. So your rendered macro will not get updated props until a user manually changes data in the dynamically rendered config form fields.
  • So in order to then get the user to see a red button I have had to save the MacroConfig user input to a contentProperty and then compare that data to the currently accessible useConfig data in the rendered macro. If there’s a mismatch I display a GIF to the user in an attempt to educate them on how to use the stupid autosave UX of the macro config sidebar.
  • The “autosave” sounds great in theory. But it’s not autosave onKeyUp. No, the user needs to either press enter or click outside of an input field. If you click outside of the sidebar it hides the sidebar. It’s incredibly unintuitive. Even the folks reviewing my marketplace app submissions don’t understand how to use it (I literally just sent a Loom to explain it). Autosave without actually saving on each keystroke is a truly bad UX decision. And there needs the ability to programmatically call useConfig() to avoid unsynced data between the config sidebar and the rendered macro.


  • I like to bulk build apps in a mono-repo to maximize the use of my time since the static Marketplace homepage (same featured apps every bloody day!) and Cloud Fortified program (an outrageous $5k per app to join!) discriminate against all but the largest entrenched app vendors. So you really need to play the longtail if you want to eat. To achieve this I had to create 20 separate manifest files and a batch file to loop deploy the apps.
  • forge lint will lint the entire codebase and not just the specific app you’re deploying/testing. Which meant if one app only required a subset of permissions, I still had to include the same permissions across all 20 manifests in order for Forge to allow the deployment.
  • Manifest permission naming rules randomly changed halfway through development. The permission docs are out of date and don’t reflect what the latest version of forge lint will throw at you.
  • Your personal name used to signup to access the Developer Console will be shown to end users in the macro insert dropdown and in the MacroConfig sidebar. It’s being fixed, but my apps now live on the marketplace show my full name to the user instead of my vendor name. Here’s the ticket to follow: [FRGE-636] - Ecosystem Jira. Somehow I was the first person to bring this to Atlassian’s attention.

That’s as much as I can remember. Hopefully it helps folks on the Forge team make some improvements.

Really hoping the team workout a way for me to run my static Connect apps inside a Forge-like sandbox, because I have no interest in migrating them across given the level of pain that will involve.



Great summary :+1:

Let me join in on this :wink:

  • Storage limit was upped to 128 KB which is great but I will have to implement a lot of logic to split up larger data and query+merge them on read. That is really not that great. I would be happy with 5MB already, but Nathans proposal sounds even better :slight_smile:

  • The permission linting errors really confuse me too. Atlassian please update the docs, thanks :slight_smile: I do not know what I need to change to make the linting go green.

warning  There are deprecated scopes 'scopes' in the manifest.yml file: 
'read:jira-user, read:jira-work, write:jira-work, manage:jira-configuration'. 
You need to update this app to use new scopes and remove the deprecated scopes. 
Learn more at: https://go.atlassian.com/forge-permissions.  

Awesome, yeah valid-permissions-required is what I was referring to!

Ideally the KV storage limit should be dropped and the KV splitting occurs behind the API. Perhaps with more features on storage.query() so it behaves more like a structured database.


Another :+1: for a good summary.

As for MacroConfig gripes, we stumbled over some of them early on as well, and filed [FRGE-209] - Ecosystem Jira (Allow to set macro configuration values from code) and [FRGE-223] - Ecosystem Jira (Allow Text and other non Form UI Kit components in MacroConfig) quite a while back. Both are still sitting on ‘Gathering Interest’ and could use some upvotes/chiming in accordingly.


[…] my apps now live on the marketplace show my full name to the user instead of my vendor name. Here’s the ticket to follow: [FRGE-636] - Ecosystem Jira. Somehow I was the first person to bring this to Atlassian’s attention.

This has already been discussed in How to change macro icon and description in Forge?, but didn’t receive any attention by Atlassian either back then, so thanks for filing the issue (the issue tracker seemed comparatively unmaintained for a while, so filing issues for topics like this felt futile for a bit).

Speaking of, another glaring Forge macro omission is the Missing icon (and category) support for macros (FRGE-211), which is ‘in review’ and supposed to be ‘implemented soon’ as of 2021-02-24 - while not affecting the functionality, it’s not exactly an incentive for adopting Forge, if Forge macros are not well discoverable, always sorted last, and look unprofessional, summing up to a competitive disadvantage.

1 Like

@nathanwaters this is perfect feedback for us. Just letting you know that a lot of people from Forge team will read this in the next couple of days.


@nathanwaters, as @dmitrii said this is great feedback for us. The whole Forge product team have been sharing and discussing your thread this week. I’ll have a go at colating an overall response and others might chip in on specific points.


  • With regard to the use of various NPM packages, we know this can be frustrating and have started a project to fundamentally re-think how the Forge runtime works. We want to allow more flexibility while also staying true to the Forge trust model. It’s a big piece of work but should hopefully bring some big improvements to the platform in the second half of 2022.
  • The same work should also bring a bunch of overall stability and performance improvements (including the Tunnel).
  • Multi-user app ownership and support for CI/CD are known gaps in the Forge offering and road mapped for later 2022.
  • Observability is also something we’re also working on and you’ll see that continue to improve throughout this year. Did you know that you can also view your logs in the developer console? We’d be keen to hear any more specifics you have on the types of logs you need and how you’d prefer to access them.
  • With regard to cost, our position is still the same. We plan to keep Forge as free as we can. Its primary purpose is to improve Atlassian products and create value for our customers.


As you pointed out, we recently increased the limits but we know there’s still more to be done. I see you’ve already given @sushantBista some more feedback on that so thank you.

UI Kit

UI Kit exists so that developers can quickly and easily build front ends that Atlassian customers find intuitive and familiar. There is a deliberate bias toward simplicity over flexibility.

That said, we know there are lots of cases where an extra level of control would be helpful and we may evolve UI Kit to allow for that in future. You raise some fair points around the current quirks and issues and we’ll keep those in mind. Every bit of feedback helps shape our vision for the future of UI Kit.

At the moment we’re more focused on closing some of the feature gaps in Custom UI but are committed to improving UI Kit in the long term. Stay tuned.


We know that the options for MacroConfig are extremely limited at the moment and it’s a blocker for many of our popular Confluence apps moving over to Forge. Custom UI for MacroConfig is one of Forge’s top voted feature requests.

I don’t have any specific updates to share on this at the moment but know that it’s high on our priorities.


  • I’d love to hear more about how you think we might best support your mono repo set-up. With regard to the 20 manifest files - are you suggesting you might prefer a single manifest that applies to multiple Forge apps in a single repo? Being able to lint individual and deploy multiple apps easily from the same repo is a fair ask and something for us to think about.

  • With regard to the permissions changes, I appreciate that was painful and apologise for how messy that was. We’ve taken some good learnings from that rollout and are doing everything we can to make sure something similar doesn’t happen in the future.

  • The problem with the developer’s name being displayed on marcos is currently being worked on should be fixed this month.


Thanks again for taking the time to give us such in-depth feedback. We appreciate a good rant :grin: Most of these challenges will take time will take time to solve but they are top-of-mind for us and you’ll see some big improvements over the course of the year.


Thanks mate!

Yeah so the way I did Forge mono repo was a manifest for each app: manifest_APP1.yml, manifest_APP2.yml etc and then this batch script:

 for %%f in (manifest_*.yml) do (
   rename "%cd%\%%f" "manifest.yml"
   forge deploy -e production
   rename "%cd%\manifest.yml" "%%f"

Then routed the particular app to an exported render() function:

    - key: macro
      handler: macro._BUTTONS
    - key: config
      handler: config._BUTTONS

But forge deploy seems to lint (and throw permission errors) on the entire code base instead of following the rabbit hole of exported/imported components.

Dynamic manifest files would be useful. eg the way I pulled off a mono repo deployment on Connect (which is hilariously annoying my slow competitors) was by generating the atlassian-connect.json via an API endpoint running in a Cloudflare Worker.

1 Like


Another major one I forgot: when inserting a macro for the first time it displays the “Allow Access” prompt. However that button is unclickable in the editor.

Not sure how that terrible UX decision made it to production.

It’s currently set to be fixed Q4 2022 which seems a bit ridiculous when the UX is so flawed that I have users emailing me wondering how they can even begin to use the app.

Can you escalate that one?


We have filed an issue for that in June 2021 already, indeed questionable that it has been postponed in favor of a fix that still seems 6 months away at least:

1 Like