CINXE.COM

Use the Forge hosted storage in a Confluence macro

<!DOCTYPE html> <html lang="en"> <head><meta name="csrf" content="gkrzrMYU-ZcFIqIFe5a2bFguTrYyxWyHa_pU"> <link rel="preconnect" href="https://dac-static.atlassian.com" crossorigin /> <link rel="dns-prefetch" href="https://dac-static.atlassian.com" /> <script defer type="text/javascript" src="https://dac-static.atlassian.com/_static/polyfills.2fbfe3cfc70c64f23379.bundle.js"></script> <script defer type="text/javascript" src="https://dac-static.atlassian.com/_static/documentation-changelogs-docs-index-rest-api-docs-rest-docs-search-graphql-docs-graphql-sandbox-jsapi-connect-module-pages-analytics-and-cookie-preferences-homepage-errors-supportdesk.37387166404821985a5b.bundle.js"></script><script defer type="text/javascript" src="https://dac-static.atlassian.com/_static/documentation-changelogs-docs-index-rest-api-docs-rest-docs-search-graphql-docs-graphql-sandbox-jsapi-connect-module-pages-homepage-errors-supportdesk.3cdb946b9cf346a1c81f.bundle.js"></script><script defer type="text/javascript" src="https://dac-static.atlassian.com/_static/documentation.3cb109c065b5662b0593.bundle.js"></script> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta data-react-helmet="true" name="description" content="Learn how to build a Confluence macro using Forge hosted storage for site-wide definition sharing."/> <meta name="dac:version" content="1.5800.1062"> <link rel="shortcut icon" href="https://dac-static.atlassian.com/favicon.ico" type="image/x-icon"> <link rel="icon" href="https://dac-static.atlassian.com/favicon.ico" type="image/x-icon"> <link rel="search" href="https://dac-static.atlassian.com/opensearch.xml" type="application/opensearchdescription+xml"> <script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8=" type="text/javascript">window.__DATA__ = {"jiraIssueCollectorId":"ee87e716","page":{"document":[{"type":"markdown","content":"\n# Use Forge hosted storage in a Confluence macro\n\nThis tutorial describes how to build an app for sharing definitions for\nterminology and acronyms across an entire Confluence site.\nThe app uses Forge hostes storage to store definitions, which allows them to be\nshared between several macros and accessed from the site administration.\n\nIn this tutorial you will learn how to persist and retrieve data from Forge hosted storage\n(specifically, the [Key-Value Store](/platform/forge/runtime-reference/storage-api))\nand display the results in a table.\n\n"},{"type":"shortcode","name":"tip","arguments":[],"content":"\nThis tutorial has an accompanying [Bitbucket repository](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/master/).\nYou'll find a link to a git tag at the end of each step which you can use to compare\nwith your code or to skip ahead.\n\nIf you are cloning this repository, use `forge register` before you begin to create a new ID\nfor the app under your account.\n"},{"type":"markdown","content":"\n\n## Before you begin\n\n"},{"type":"markdown","content":"This tutorial assumes you're already familiar with the basics of Forge development.\nIf this is your first time using Forge, see [Getting started](/platform/forge/getting-started/) first."},{"type":"markdown","content":"\n\nTo complete this tutorial, you need the latest version of Forge CLI. To update your CLI version, run `npm install -g @forge/cli@latest`\non the command line.\n\n"},{"type":"markdown","content":"### Set up a cloud developer site\n\u003c!--\nUse this snippet for Jira/Confluence tutorials\n-->\n\nAn Atlassian cloud developer site lets you install and test your app on\nConfluence and Jira products set up for you. If you don't have one yet, set it up now:\n\n1. Go to [http://go.atlassian.com/cloud-dev](http://go.atlassian.com/cloud-dev) and\ncreate a site using the email address associated with your Atlassian account.\n1. Once your site is ready, log in and complete the setup wizard.\n\nYou can install your app to multiple Atlassian sites. However, app\ndata won't be shared between separate Atlassian sites, products, \nor Forge environments.\n\nThe limits on the numbers of users you can create are as follows:\n\n- Confluence: 5 users\n- Jira Service Management: 1 agent\n- Jira Software and Jira Work Management: 5 users\n\n"},{"type":"shortcode","name":"warning","arguments":[],"content":"\nThe Atlassian Marketplace doesn't currently support cross-product apps. If your app supports multiple products,\nyou can publish two separate listings on the Marketplace, but your app won't be able to make API calls across\ndifferent products and instances/installations.\n"},{"type":"markdown","content":"\n\n## Step 1: Create your app\n\nCreate an app based on the Hello world template. Using your terminal complete\nthe following:\n\n1. Navigate to the directory where you want to create the app.\n1. Create your app by running:\n\n ``` shell\n forge create\n ```\n1. Enter a name for the app. For example, _definitions-macro_.\n1. Select the *UI Kit* category.\n1. Select the *Confluence* product.\n1. Select the _confluence-macro_ template.\n\n1. Your app has been created in a directory with the same name as your app, for example\n _definitions-macro_. Open the app directory to see the files associated with your app.\n1. Install the latest version of the Forge API package\n\n ``` shell\n npm install --save @forge/api@latest\n ```\n\n1. Enable the Key-Value Store by adding the `storage:app` scope to the `manifest.yml`\n file. [Learn more about adding scopes to call an Atlassian REST API]\n (/platform/forge/add-scopes-to-call-an-atlassian-rest-api/).\n\n ``` yaml\n permissions:\n scopes:\n - storage:app\n ```\n\n1. Enable the [config](https://developer.atlassian.com/platform/forge/add-configuration-to-a-macro-with-ui-kit/) so that it can appear in the macro by adding `config: true` under `macro`.\n\n ``` yaml\n modules:\n macro:\n ...\n config: true\n ```\n\nYou can check your app against [step 1](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-1/)\nin the tutorial repository.\n\n## Step 2: Deploy and install your app\n\n"},{"type":"markdown","content":"1. Navigate to the app's top-level directory and deploy your app by running:\n\n ``` shell\n forge deploy\n ```\n\n1. Install your app by running:\n\n ``` shell\n forge install\n ```\n\n1. Select your Atlassian product using the arrow keys and press the enter key.\n\n1. Enter the URL for your development site. For example, *example.atlassian.net*.\n [View a list of your active sites at Atlassian administration](https://admin.atlassian.com/).\n \nOnce the *successful installation* message appears, your app is installed and ready \nto use on the specified site.\nYou can always delete your app from the site by running the `forge uninstall` command.\n\n"},{"type":"shortcode","name":"note","arguments":[],"content":"\nRunning the `forge install` command only installs your app onto the selected product.\nTo install onto multiple products, repeat these steps again, selecting another product each time. \nNote that the Atlassian Marketplace \n[does not support cross-product apps yet](/platform/marketplace/listing-forge-apps/#what-if-my-app-supports-multiple-products-).\n\nYou must run `forge deploy` before running `forge install` in any of the Forge environments.\n"},{"type":"markdown","content":"\n\nNext, add your new Confluence macro to a page. To view log invocations, start a [tunnel](/platform/forge/tunneling/) to your app:\n\n```\nforge tunnel\n```\n\nYou can check your app against [step 2](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-2/)\nin the tutorial repository.\n\n## Step 3: Add a configuration dialog to the macro\n\n1. Within the `src/frontend/index.jsx` file, add a new component named `Config` containing [TextArea](https://developer.atlassian.com/platform/forge/ui-kit/components/text-area/) and Label from the `@forge/react` library. This configuration form allows a user of the macro to specify a set of definitions to show in a table.\n\n ``` javascript\n const Config = () => {\n return (\n \u003c>\n \u003cLabel labelFor=\"terms\">Terms to include (one per line)\u003c/Label>\n \u003cTextArea name=\"terms\" id=\"terms\" defaultValue=\"\" isRequired />\n \u003c/>\n )\n };\n ```\n\n1. Add the `Config` function to the `ForgeReconciler` to allow for configuration changes, under the existing `ForgeReconciler.render()` for `App`.\n\n ``` javascript\n ForgeReconciler.render(\n \u003cReact.StrictMode>\n \u003cApp />\n \u003c/React.StrictMode>\n );\n\n ForgeReconciler.addConfig(\u003cConfig />);\n ```\n\n1. Add the [`useConfig`](https://developer.atlassian.com/platform/forge/ui-kit/hooks/use-config/) hook to the `App` component. This hook allows the app\n to access configuration set by the user in the macro configuration dialog, and defaults to an empty object if undefined.\n If there is no list of terms found in config, `terms` defaults to an empty array.\n App currently returns the information wrapped in the [Text](https://developer.atlassian.com/platform/forge/ui-kit/components/text/) component.\n\n ``` javascript\n const App = () => {\n const config = useConfig() || {};\n const terms = config.terms ? config.terms.split(\"\\n\") : [];\n\n if (terms.length === 0) {\n return (\n \u003cText>No Terms\u003c/Text>\n );\n }\n\n return (\n \u003cText>{terms.join(\",\")}\u003c/Text>\n );\n };\n ```\n\nYou can check your app against [step 3](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-3/)\nin the tutorial repository.\n\n## Step 4: Fetch a list of definitions from storage\n\nYour app makes use of the JavaScript API provided in the `@forge/api` package to\ninteract with the Key-Value Store. This package provides methods for reading,\nwriting, and querying data within the Key-Value Store.\n\nThis tutorial starts with reading a list of definitions from the Key-Value Store.\nInitially the results are empty; adding definitions is covered in a later stage.\n\nThe app stores key entities based on the term, with the following format:\n\n``` typescript\ninterface Term {\n definition: string;\n term: string;\n}\n```\n\n1. Within `src/resolvers/index.js`, add a `getDefinition` function to load a definition given a term.\n\n ``` javascript\n import Resolver from '@forge/resolver';\n import { storage } from '@forge/api';\n\n const resolver = new Resolver();\n\n // Create a key composed from the term\n function termKey(term) { \n return `term-${term}`;\n }\n\n async function getDefinition(term) {\n const value = await storage.get(termKey(term));\n return value ? value.definition : \"\";\n }\n\n export const handler = resolver.getDefinitions();\n ```\n\n1. Also create a `getDefinitions` function using `resolver` to turn a list of terms into a list of definitions.\n\n ``` javascript\n resolver.define('getDefinitions', async(req) => {\n const pendingDefinitions = req.payload.terms.map((term) => getDefinition(term));\n return await Promise.all(pendingDefinitions);\n })\n ```\n\n "},{"type":"shortcode","name":"note","arguments":[],"content":"\n This function makes use of the `Promise.all` operation to turn a list\n of pending promises into a single promise. The resulting promise resolves to an\n array of definitions when awaited.\n "},{"type":"markdown","content":"\n\n1. Inside the `src/frontend/index.jsx` file, add a new hook within the `App` component for `definitions`.\n\n ``` javascript\n const [definitions, setDefinitions] = useState([]);\n ```\n\n1. In the `src/frontend/index.jsx` file, define an async helper function called `populateDefinitions` inside the `App` component using [useEffect](https://developer.atlassian.com/platform/forge/ui-kit-hooks-reference/#useeffect). This invokes the resolver with key `getDefinitions`. \n\n ``` javascript\n useEffect(() => {\n const populateDefinitions = async() => {\n if (terms.length !== 0) {\n const data = await invoke('getDefinitions', { terms: terms });\n setDefinitions(data);\n }\n }\n\n populateDefinitions();\n }, [terms, invoke, setDefinitions]);\n ```\n\n1. Change the return of the `App` component to load the\ndefinitions for the provided terms list. Since no definitions have been provided yet, definitions should be empty.\n\n ``` javascript\n const App = () => {\n const [definitions, setDefinitions] = useState([]);\n const config = useConfig() || {};\n const terms = config.terms ? config.terms.split(\"\\n\") : [];\n\n useEffect(() => {\n const populateDefinitions = async() => {\n if (terms.length !== 0) {\n const data = await invoke('getDefinitions', { terms: terms });\n setDefinitions(data);\n }\n }\n\n populateDefinitions();\n }, [terms, invoke, setDefinitions]);\n\n return (\n \u003c>\n \u003cText>{terms.join(\",\")}\u003c/Text>\n \u003cText>{definitions.join(\",\")}\u003c/Text>\n \u003c/>\n );\n };\n ```\n\nYou can check your app against [step 4](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-4/)\nin the tutorial repository.\n\n## Step 5: Create the definitions table\n\n![The definition table](/platform/forge/images/definition-macro-step-5.png)\n\nIn this step, you'll add a [Dynamic Table](https://developer.atlassian.com/platform/forge/ui-kit/components/dynamic-table/) to the definitions macro to show the list of terms side by side with a list of definitions.\n\nIt can be useful when building a UI Kit app to group elements together into reusable components.\nFor this app, we will add a `DefinitionTable` component.\n\n1. Create a new file named `definition-table.jsx` in `src/frontend`.\n1. In this file, create a component named `DefinitionTable`. This component renders a list of definitions in a table. Also add an object called `head`, which will contain the data for the headers of `DefinitionTable`. Also remember to import `invoke` for later. \n\n ``` javascript\n import React from 'react';\n import { DynamicTable } from \"@forge/react\";\n import { invoke } from '@forge/bridge';\n\n // Render the table headers\n const head = {\n cells: [\n {\n key: \"term\",\n content: \"Term\",\n isSortable: true,\n },\n {\n key: \"definition\",\n content: \"Definition\",\n shouldTruncate: true,\n isSortable: true,\n },\n {\n key: \"buttons\", // Additional column for buttons on each row\n content: \"\",\n shouldTruncate: true,\n isSortable: true,\n },\n ],\n };\n\n // Render the Definition Table\n export const DefinitionTable = ({ terms, definitions }) => {\n return (\n \u003cDynamicTable\n head={head}\n emptyView=\"No terms provided, please press Edit on the app and add terms in the Configuration box\"\n />\n );\n };\n ```\n\n1. In the same file, add an object called `row` - this will be used to render each row in the definitions table. Also add a `createKey` function that generates a key for each term in the row. \n\n ``` javascript\n // create a key for each term\n const createKey = (input) => {\n return input ? input.replace(/\\s/g, \"\") : input; // remove whitespace\n }\n\n // Render the Definition Table\n export const DefinitionTable = ({ terms, definitions }) => {\n const rows = terms.map((term, index) => ({\n key: `row-${index}-${term}`,\n cells: [\n {\n key: createKey(term),\n content: term\n },\n {\n key: index,\n content: definitions[index],\n colSpan: 2,\n },\n ],\n }));\n\n return (\n \u003cDynamicTable\n head={head}\n rows={rows}\n emptyView=\"No terms provided, please press Edit on the app and add terms in the Configuration box\"\n />\n );\n }\n ```\n\n1. Add an import for the `DefinitionTable` component in `src/frontend/index.jsx`.\n\n ``` javascript\n import { DefinitionTable } from './definition-table';\n ```\n\n1. Add this table to your existing macro in `src/frontend/index.jsx`.\n\n ``` javascript\n return (\n \u003c>\n \u003cDefinitionTable terms={terms} definitions={definitions}/>\n \u003c/>\n );\n ```\n\nYou can check your app against [step 5](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-5/)\nin the tutorial repository.\n\n## Step 6: Allow a user to add a definition\n\n![The usable definition table](/platform/forge/images/definition-macro-step-6a.png)\n\nAt this stage, there's still no data stored for the app. In this step, you'll add the\nability to store a definition for a term.\n\n1. Add a `saveDefinition` method to the `src/resolvers/index.js` file.\n\n ``` javascript\n resolver.define('saveDefinition', async(req) => {\n const { term, definition } = req.payload;\n await storage.set(termKey(term), { term, definition });\n })\n ```\n\n1. Add a `removeDefinition` method to the `src/resolvers/index.js` file.\n\n ``` javascript\n resolver.define('removeDefinition', async(req) => {\n let term = req.payload.term;\n await storage.delete(termKey(term)); \n })\n ```\n\n1. In `src/frontend/definition-table.jsx`, within the `DefinitionTable` component, set up React hooks that will be used to open an input modal. This enables a user to provide a definition for a term. \n\n ``` javascript\n const { handleSubmit, register, getFieldId } = useForm();\n const [term, setTerm] = useState('');\n const [definition, setDefinition] = useState('');\n const [loadingState, setLoadingState] = useState(false);\n\n const [inputIsOpen, setInputIsOpen] = useState(false);\n const openInputModal = () => setInputIsOpen(true);\n const closeInputModal = () => setInputIsOpen(false);\n ```\n\n1. Also set up React hooks that will be used to open a delete confirmation modal as well. This enables a user to delete a provided definition for a term.\n\n ``` javascript\n const [deleteIsOpen, setDeleteIsOpen] = useState(false);\n const openDeleteModal = () => setDeleteIsOpen(true);\n const closeDeleteModal = () => setDeleteIsOpen(false);\n ```\n\n1. Add two [Modals](https://developer.atlassian.com/platform/forge/ui-kit/components/modal/) in the return statement of the `DefinitionTable` component. When the user clicks submit for the input modal, the `saveDefinition` resolver callback is invoked in the [Form](https://developer.atlassian.com/platform/forge/ui-kit/components/form/) component and then the modal closed. When the user clicks submit for the delete modal, the `removeDefinition` resolver callback is invoked. \n\n ``` javascript\n return (\n \u003c>\n \u003cDynamicTable\n head={head}\n rows={rows}\n emptyView=\"No terms provided, please press Edit on the app and add terms in the Configuration box\"\n isLoading={loadingState}\n />\n\n \u003cModalTransition>\n {inputIsOpen && (\n \u003cModal onClose={closeInputModal}>\n \u003cForm\n onSubmit={handleSubmit(submitInput)}\n >\n \u003cModalHeader>\n \u003cModalTitle>{`Add definition for ${term}`}\u003c/ModalTitle>\n \u003c/ModalHeader>\n \u003cModalBody>\n \u003cLabel labelFor={getFieldId(\"definition\")}>{`Definition for ${term}`}\u003c/Label>\n \u003cTextArea name=\"definition\" id=\"definition\" defaultValue={definition} {...register(\"definition\", {\n required: true\n })} />\n \u003c/ModalBody>\n \u003cModalFooter>\n \u003cButton appearance=\"subtle\" onClick={closeInputModal}>\n Cancel\n \u003c/Button>\n \u003cButton appearance=\"primary\" onClick={closeInputModal} type=\"submit\">\n Submit\n \u003c/Button> \n \u003c/ModalFooter>\n \u003c/Form>\n \u003c/Modal>\n )}\n \u003c/ModalTransition>\n\n \u003cModalTransition>\n {deleteIsOpen && (\n \u003cModal onClose={closeDeleteModal}>\n \u003cForm\n onSubmit={handleSubmit(submitDelete)}\n >\n \u003cModalHeader>\n \u003cModalTitle>{`Delete definition for ${term}?`}\u003c/ModalTitle>\n \u003c/ModalHeader>\n \u003cModalFooter>\n \u003cButton appearance=\"subtle\" onClick={closeDeleteModal}>\n Cancel\n \u003c/Button>\n \u003cButton appearance=\"danger\" onClick={closeDeleteModal} type=\"submit\">\n Delete\n \u003c/Button> \n \u003c/ModalFooter>\n \u003c/Form>\n \u003c/Modal>\n )}\n \u003c/ModalTransition>\n \u003c/>\n );\n ```\n\n1. Add two submit functions for the input and delete modals respectively within the `DefinitionTable` component. \n\n ``` javascript\n const submitInput = async({ definition }) => {\n setLoadingState(true);\n await invoke('saveDefinition', { term: term, definition: definition })\n setLoadingState(false);\n };\n\n const submitDelete = async() => {\n setLoadingState(true);\n await invoke('removeDefinition', { term: term })\n setLoadingState(false);\n };\n ```\n\n1. Create a `generateRow` function that uses [useCallback](https://developer.atlassian.com/platform/forge/ui-kit/#supported-hook-types). This will return the definition of a term if it exists, along with an `Edit` and `Delete` button for modifying the definition. This is formatted using [Inline](https://developer.atlassian.com/platform/forge/ui-kit/components/inline/). If the definition for the term does not exist, it will render an `Add Definition` button. Otherwise, it will render a [Spinner](https://developer.atlassian.com/platform/forge/ui-kit/components/spinner/). \n\n ``` javascript\n const generateRow = useCallback(\n (index, term, generatedDefinition) => {\n let definitionContent = \u003cSpinner />;\n if (generatedDefinition === \"\") {\n definitionContent = \n \u003cButton appearance=\"default\" onClick={() => {\n setTerm(term);\n setDefinition(\"\");\n openInputModal();\n }}>\n Add Definition\n \u003c/Button>\n } else if (generatedDefinition) {\n definitionContent = \n \u003cInline spread=\"space-between\">\n \u003cText>{generatedDefinition}\u003c/Text>\n \u003cButtonGroup>\n \u003cButton appearance=\"default\" spacing=\"compact\" onClick={() => {\n setTerm(term);\n setDefinition(generatedDefinition);\n openInputModal();\n }}>\n Edit\n \u003c/Button>\n \u003cButton appearance=\"danger\" spacing=\"compact\" onClick={() => {\n setTerm(term);\n openDeleteModal();\n }}>\n Delete\n \u003c/Button>\n \u003c/ButtonGroup>\n \u003c/Inline>\n }\n \n return ({\n key: `row-${index}-${term}`,\n cells: [\n {\n key: createKey(term),\n content: term\n },\n {\n key: index,\n content: definitionContent,\n colSpan: 2,\n },\n ],\n })\n },\n [setTerm, setDefinition, openInputModal, openDeleteModal, createKey, setTerm, setDefinition, openInputModal, openDeleteModal]);\n ```\n\n1. Add `generateRow` function to the rows variable, so it will be rendered in `\u003cDynamicTable>`.\n\n ``` javascript\n const rows = terms.map((term, index) => (\n generateRow(index, term, definitions[index])\n ));\n ```\n\n1. Stop tunneling your app and deploy it by running:\n\n ``` shell\n forge deploy\n ```\n\nYou can check your app against [step 6](https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-6/)\nin the tutorial repository.\n\n## Next steps\n\nAt this point your app is able display a list of terms and their associated definitions.\nThe app stores definitions in the storage service, and shares these across all\nthe instances of the macro in the site.\n\nExplore Forge storage in further detail over the following pages:\n\n- Read [App storage options](/platform/forge/storage/) for an overview of the different ways Forge\napps can store data\n- Read about the [Key-Value Store](/platform/forge/runtime-reference/storage-api) which\n details the JavaScript API.\n- Learn more about how [Queries](/platform/forge/runtime-reference/storage-api-query) can\n be run against data stored in the Key-Value Store.\n- View the [Limits](/platform/forge/platform-quotas-and-limits/#storage-quotas) that apply\n to apps using Forge hosted storage.\n"}],"metadata":{"source":"https://bitbucket.org/atlassian-developers/forge-docs/src/master/content/platform/forge/create-confluence-macro-with-storage-api.md?at=master&mode=edit&fileviewer=file-view-default&spa=0","title":"Use the Forge hosted storage in a Confluence macro","platform":"platform","description":"Learn how to build a Confluence macro using Forge hosted storage for site-wide definition sharing.","product":"forge","category":"devguide","subcategory":"learning","guides":"tutorials","date":"2024-10-30","enabledVersion":"1.5800.1062"},"deprecatedNavigation":{"title":"Forge","name":"Forge","url":"/platform/forge/","categories":[{"title":"Guides","name":"devguide","url":"/platform/forge/","indexLinkTitle":"About Forge","subcategories":[{"title":"Get started","name":"intro","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Introduction to Forge","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"The Forge platform","url":"/platform/forge/introduction/the-forge-platform/"},{"title":"Why build with Forge","url":"/platform/forge/introduction/why-build-with-forge/"}]},{"title":"Migrate your Connect app","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Adopting Forge from Connect","url":"https://developer.atlassian.com/platform/adopting-forge-from-connect/"}]},{"title":"Learn","name":"learn","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Example apps","name":"exampleapps","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Bitbucket","url":"/platform/forge/example-apps-bitbucket/"},{"title":"Compass","url":"/platform/forge/example-apps-compass/"},{"title":"Confluence","url":"/platform/forge/example-apps-confluence/"},{"title":"Jira","url":"/platform/forge/example-apps-jira/"},{"title":"Jira Service Management","url":"/platform/forge/example-apps-jsm/"},{"title":"Rovo","url":"/platform/forge/example-apps-rovo/"}]},{"title":"Guided tutorials","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/tutorials-and-guides/"},{"title":"Forge, Compass, and AWS CloudWatch","url":"/platform/forge/forge-compass-cloudwatch/"},{"title":"Schedule web triggers","url":"/platform/forge/add-scheduled-trigger/"},{"title":"Debug functions using IntelliJ","url":"/platform/forge/debug-functions-using-intellij/"},{"title":"Debug functions using VS Code","url":"/platform/forge/debug-functions-using-vscode/"},{"title":"Profile app performance with tunnel debugger","url":"/platform/forge/profiling-node-js-app-code-tunnel/"},{"title":"Implement a dynamic profile retriever","url":"/platform/forge/implement-a-dynamic-profile-retriever-with-external-authentication/"},{"title":"Migrate an app from Connect to Forge","url":"https://developer.atlassian.com/platform/adopting-forge-from-connect/migrate-macro"},{"title":"Migrate an app from UI Kit 1 to UI Kit","url":"/platform/forge/ui-kit/migration-example/"},{"title":"Set up continuous delivery","url":"/platform/forge/set-up-cicd/"},{"title":"Queue app interactions with Storage API","url":"/platform/forge/storage-api-limit-handling/"},{"title":"Use a long-running function","url":"/platform/forge/use-a-long-running-function"},{"title":"Use custom entities to store structured data","url":"/platform/forge/custom-entities-store-structured-data/"},{"title":"Use an external OAuth 2.0 API with fetch","url":"/platform/forge/use-an-external-oauth-2.0-api-with-fetch/"},{"title":"Add routing to a full-page app in Jira","url":"/platform/forge/add-routing-to-a-full-page-app/"},{"title":"Use the storage API in Confluence","url":"/platform/forge/create-confluence-macro-with-storage-api"},{"title":"Add custom configuration to a macro","url":"/platform/forge/add-custom-configuration-to-a-macro"},{"title":"Using rich body macros","url":"/platform/forge/using-rich-text-bodied-macros"},{"title":"Rovo","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Extend Atlassian products with a Forge Rovo agent","url":"/platform/forge/extend-atlassian-products-with-a-forge-rovo-agent/"},{"title":"Build a Rovo Agent app","url":"/platform/forge/build-a-hello-world-rovo-agent/"},{"title":"Build a Q&A Rovo Agent for Confluence","url":"/platform/forge/build-a-q-and-a-rovo-agent-for-confluence"},{"title":"Build a Jira issue analyst Rovo Agent","url":"/platform/forge/build-a-jira-issue-analyst-rovo-agent"}]},{"title":"Jira","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Build a hello world app in Jira","url":"/platform/forge/build-a-hello-world-app-in-jira/"},{"title":"Automate Jira with triggers","url":"/platform/forge/automate-jira-using-triggers/"},{"title":"Build a Jira comments summarizer app with OpenAI","url":"/platform/forge/build-jira-comments-summarizer-with-openai/"},{"title":"Use a workflow validator to check issue assignments","url":"/platform/forge/check-jira-issues-assigned-using-workflow-validator/"},{"title":"Build a custom UI app","url":"/platform/forge/build-a-custom-ui-app-in-jira/"}]},{"title":"Jira Service Management","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Build a hello world app in Jira Service Management","url":"/platform/forge/build-a-hello-world-app-in-jira-service-management/"},{"title":"Import third party data into Assets","url":"/platform/forge/assets-import-app/"},{"title":"Use Async Events API to queue jobs to import objects into Assets","url":"/platform/forge/queue-events-with-async-events-api-to-import-assets/"},{"title":"Build a custom UI app","url":"/platform/forge/build-a-custom-ui-app-in-jira-service-management/"}]},{"title":"Confluence","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Build a hello world app in Confluence","url":"/platform/forge/build-a-hello-world-app-in-confluence/"},{"title":"Create a question generator app in multiple languages using i18n","url":"/platform/forge/create-a-question-generator-app-in-multiple-languages-using-i18n/"},{"title":"Create a quiz app using UI Kit","url":"/platform/forge/create-a-quiz-app-using-ui-kit/"},{"title":"Add configuration to a macro with UI Kit","url":"/platform/forge/add-configuration-to-a-macro-with-ui-kit/"},{"title":"Create a logo designer app using the Frame component (Preview)","url":"/platform/forge/ui-kit/components/frame-tutorial/"},{"title":"Use space settings and content byline to implement space news","url":"/platform/forge/space-news/"},{"title":"Use content actions to count page macros","url":"/platform/forge/macros-in-the-page/"},{"title":"Build a Custom UI app","url":"/platform/forge/build-a-custom-ui-app-in-confluence/"},{"title":"Build a Confluence keyword extractor with OpenAI","url":"/platform/forge/build-confluence-keyword-extractor-with-openai/"},{"title":"Use highlighted text in a Confluence app","url":"/platform/forge/create-confluence-contextmenu-module/"},{"title":"Create a GIPHY app using UI kit on Confluence","url":"/platform/forge/create-a-giphy-app-using-the-ui-kit/"}]},{"title":"Bitbucket","name":"guidedtutorials","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Extend Bitbucket Cloud","url":"/platform/forge/extend-bitbucket-cloud/"},{"title":"Build a hello world app in Bitbucket","url":"/platform/forge/build-a-hello-world-app-in-bitbucket/"},{"title":"Automate Bitbucket with triggers","url":"/platform/forge/automate-bitbucket-using-triggers/"},{"title":"Build a pull request title validator with custom merge checks","url":"/platform/forge/build-a-pull-request-title-validator-with-custom-merge-checks/"},{"title":"Orchestrate your builds using Dynamic Pipelines","url":"/platform/forge/orchestrate-your-builds-using-dynamic-pipelines/"}]}]},{"title":"Atlassian developer glossary","url":"https://developer.atlassian.com/developer-guide/glossary/"}]}]},{"title":"Plan & design","name":"plandesign","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"App architecture","name":"apparchitecture","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Events and triggers","url":"/platform/forge/events/"},{"title":"Hosted storage","url":"/platform/forge/storage/"},{"title":"Hosted storage data lifecycle","url":"/platform/forge/storage-reference/hosted-storage-data-lifecycle/"},{"title":"Manifest","url":"/platform/forge/manifest/"},{"title":"Modules","url":"/platform/forge/modules/"}]},{"title":"Platform quotas and limits","name":"quotasnadlimits","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/platform-quotas-and-limits/"}]},{"title":"User interface","name":"user-interface","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/user-interface/"},{"title":"Build with UI Kit","url":"/platform/forge/ui-kit/"},{"title":"Extend UI with custom options","url":"/platform/forge/extend-ui-with-custom-options/"},{"title":"Design tokens and theming","url":"/platform/forge/design-tokens-and-theming/"},{"title":"Internationalization","url":"/platform/forge/internationalization/"},{"title":"Understanding the UI modifications module","url":"/platform/forge/understanding-ui-modifications/"},{"title":"Jira full page modules","url":"/platform/forge/jira-full-page-modules/"}]},{"title":"Legal & privacy","name":"legalprivacy","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Forge terms of use","url":"/platform/forge/developer-terms/"},{"title":"Shared responsibility model","url":"/platform/forge/shared-responsibility-model/"},{"title":"Forge privacy and security FAQ","url":"/platform/forge/faq-privacy-security/"},{"title":"User privacy guide","url":"/platform/forge/user-privacy-guidelines/"},{"title":"Forge Data Processing Addendum","url":"/platform/forge/about-the-forge-data-processing-addendum/"},{"title":"Logging data","url":"/platform/forge/logging-guidelines/"}]},{"title":"Best practice","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"App security","url":"/platform/forge/security/"}]},{"title":"App distribution","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Promote an app from staging to production","url":"/platform/forge/staging-and-production-apps/"},{"title":"Distribute via console","url":"/platform/forge/distribute-your-apps/"}]}]},{"title":"Build","name":"build","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Development life cycle","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Developing with Forge","url":"/platform/forge/getting-started/"},{"title":"Environment configuration","url":"/platform/forge/environments-and-versions/"},{"title":"Contributors","name":"contributors","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/contributors/"},{"title":"Managing contributors","url":"/platform/forge/manage-app-contributors/"}]},{"title":"App versions","url":"/platform/forge/versions/"},{"title":"Testing and debugging","name":"testdebug","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/debugging/"},{"title":"Debug using IntelliJ","url":"/platform/forge/debug-functions-using-intellij/"},{"title":"Debug using VS Code","url":"/platform/forge/debug-functions-using-vscode/"},{"title":"Tunneling","url":"/platform/forge/tunneling/"}]}]},{"title":"App capabilities","name":"appcapabilites","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Compute","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Functions","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Invoke functions","url":"/platform/forge/function-reference/index/"},{"title":"Call a product REST API","url":"/platform/forge/apis-reference/product-rest-api-reference/"},{"title":"Call a product GraphQL API","url":"/platform/forge/apis-reference/fetch-api-product.requestgraph/"},{"title":"Verify user permissions for product APIs","url":"/platform/forge/runtime-reference/authorize-api/"},{"title":"Call an external REST API","url":"/platform/forge/runtime-reference/external-fetch-api/"},{"title":"Check user account status","url":"/platform/forge/runtime-reference/authorize-api/"},{"title":"Migrate from the legacy runtime","url":"/platform/forge/runtime-reference/legacy-runtime-migrating/"}]},{"title":"Remotes","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/remote/"},{"title":"Forge remote essentials","url":"/platform/forge/remote/essentials/"},{"title":"Send events to a remote","url":"/platform/forge/remote/sending-product-events/"},{"title":"Schedule triggers to invoke a remote","url":"/platform/forge/remote/scheduled-triggers/"},{"title":"Access Forge storage from a remote","url":"/platform/forge/remote/accessing-storage/"},{"title":"Call product APIs from a remote","url":"/platform/forge/remote/calling-product-apis/"},{"title":"Call from a Forge frontend","url":"/platform/forge/remote/calling-from-frontend/"},{"title":"Call from a Forge function","url":"/platform/forge/remote/calling-from-function/"},{"title":"Bitbucket git operations from a remote","url":"/platform/forge/remote/bitbucket-git-operations/"},{"title":"Remote observability","url":"/platform/forge/remote/observability/"},{"title":"Setting up remotes for realm pinning","url":"/platform/forge/remote/setup-dare-storage/"}]},{"title":"Web triggers","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Work with web triggers","url":"/platform/forge/runtime-reference/web-trigger/"}]},{"title":"Queues","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Use async app event queues","url":"/platform/forge/runtime-reference/async-events-api/"}]},{"title":"Events","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Platform and product events","url":"/platform/forge/events/"}]},{"title":"Reference","url":"/platform/forge/function-reference/index/"}]},{"title":"Storage","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Key value store","url":"/platform/forge/runtime-reference/storage-api-basic/"},{"title":"Entity store","url":"/platform/forge/storage-reference/storage-api-custom-entities/"},{"title":"SQL (Preview)","url":"/platform/forge/storage-reference/sql/"},{"title":"Cache (EAP)","url":"/platform/forge/storage-reference/storage-cache-api/"},{"title":"Reference","url":"/platform/forge/runtime-reference/storage-api/"},{"title":"Hosted storage data lifecycle","url":"/platform/forge/storage-reference/hosted-storage-data-lifecycle/"}]},{"title":"User interface","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"UI Kit","url":"/platform/forge/ui-kit/"},{"title":"Frontend bridge","url":"/platform/forge/apis-reference/ui-api-bridge/bridge/"},{"title":"Display conditions","url":"/platform/forge/manifest-reference/display-conditions/"},{"title":"Reference","url":"/platform/forge/ui-kit/overview/"}]},{"title":"Observability","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/remote/observability/"},{"title":"App observability in third-party tools","url":"/platform/forge/app-observability-in-third-party-tools"}]},{"title":"Automation with Forge","url":"/platform/forge/automation-with-forge/"}]},{"title":"Trust and security","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Data residency","url":"/platform/forge/data-residency/"},{"title":"Configuring app security","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Unlicensed user app access","url":"/platform/forge/access-to-forge-apps-for-unlicensed-jsm-users/"},{"title":"Scopes to call an Atlassian REST API","url":"/platform/forge/add-scopes-to-call-an-atlassian-rest-api/"},{"title":"Runtime egress permissions","url":"/platform/forge/runtime-egress-permissions/"},{"title":"Content security and egress controls","url":"/platform/forge/add-content-security-and-egress-controls/"},{"title":"App context security","url":"/platform/forge/app-context-security/"},{"title":"External authentication overview","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Configuring OAuth 2.0 providers","url":"/platform/forge/use-an-external-oauth-2.0-api-with-fetch/"},{"title":"Rotating an OAuth 2.0 client ID and secret","url":"/platform/forge/rotating-an-oauth-2.0-client-id-and-secret/"},{"title":"Common issues with external authentication","url":"/platform/forge/common-issues-with-external-authentication/"}]}]},{"title":"Runs on Atlassian","url":"/platform/forge/runs-on-atlassian/"}]},{"title":"Enterprise development","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Using Forge CLI on a corporate network","url":"/platform/forge/enterprise/use-forge-cli-on-corporate-network/"}]},{"title":"Forge releases and deprecation policy","name":"introductiontoforge","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Forge releases (includes enrolling in EAP)","url":"/platform/forge/whats-coming/"},{"title":"Forge deprecation policy","url":"/platform/forge/deprecation-policy/"}]}]},{"title":"Manage","name":"plandesign","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/manage-your-apps/"},{"title":"Observability","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Manage app alerts","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/alerts/"},{"title":"Create alert rules","url":"/platform/forge/create-alert-rules/"},{"title":"Manage alert rules","url":"/platform/forge/manage-alert-rules/"},{"title":"View open and closed alerts","url":"/platform/forge/view-open-and-closed-alerts/"}]},{"title":"Monitor app metrics","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/monitor-app-metrics/"},{"title":"Monitor invocation metrics","url":"/platform/forge/monitor-invocation-metrics/"},{"title":"Monitor API metrics","url":"/platform/forge/monitor-api-metrics/"},{"title":"Monitor cache metrics (EAP)","url":"/platform/forge/monitor-cache-metrics/"},{"title":"Monitor SQL (Preview)","url":"/platform/forge/monitor-sql-metrics/"},{"title":"Monitor usage metrics","url":"/platform/forge/monitor-usage-metrics/"},{"title":"Export app metrics","url":"/platform/forge/export-app-metrics/"}]},{"title":"Monitor app logs","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Overview","url":"/platform/forge/monitor-app-logs/"},{"title":"View app logs","url":"/platform/forge/view-app-logs/"},{"title":"Export app logs","url":"/platform/forge/export-app-logs/"},{"title":"Access app logs","url":"/platform/forge/access-app-logs/"}]},{"title":"View app installations","url":"/platform/forge/view-app-installations/"},{"title":"View app storage","url":"/platform/forge/view-app-storage/"}]},{"title":"Access","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Manage app contributors","url":"/platform/forge/manage-app-contributors/"},{"title":"Manage environments","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Forge environments","url":"/platform/forge/environments-and-versions/"},{"title":"Configuring the manifest","url":"/platform/forge/manifest-reference/"}]}]},{"title":"Distribution","name":"devlifecycle","expandAlways":true,"items":[],"nestedSubCategoryItems":[{"title":"Marketplace","url":"https://developer.atlassian.com/platform/marketplace/listing-forge-apps/"},{"title":"Distribute via console","url":"/platform/forge/distribute-your-apps/"},{"title":"CLI installation","url":"/platform/forge/cli-reference/install/"}]}]}]},{"title":"Reference","name":"reference","url":"/platform/forge/manifest-reference/","subcategories":[{"title":"CLI","name":"cli-reference","expandAlways":true,"items":[{"title":"CLI","url":"/platform/forge/cli-reference/"},{"title":"autocomplete","url":"/platform/forge/cli-reference/autocomplete"},{"title":"create","url":"/platform/forge/cli-reference/create"},{"title":"deploy","url":"/platform/forge/cli-reference/deploy"},{"title":"eligibility","url":"/platform/forge/cli-reference/eligibility"},{"title":"environments","url":"/platform/forge/cli-reference/environments","isGroup":true,"groupItems":[{"title":"create","url":"/platform/forge/cli-reference/environments-create"},{"title":"delete","url":"/platform/forge/cli-reference/environments-delete"},{"title":"list","url":"/platform/forge/cli-reference/environments-list"}]},{"title":"feedback","url":"/platform/forge/cli-reference/feedback"},{"title":"install","url":"/platform/forge/cli-reference/install","isGroup":true,"groupItems":[{"title":"list","url":"/platform/forge/cli-reference/install-list"}]},{"title":"lint","url":"/platform/forge/cli-reference/lint"},{"title":"login","url":"/platform/forge/cli-reference/login"},{"title":"logout","url":"/platform/forge/cli-reference/logout"},{"title":"logs","url":"/platform/forge/cli-reference/logs"},{"title":"providers","url":"/platform/forge/cli-reference/providers","isGroup":true,"groupItems":[{"title":"configure","url":"/platform/forge/cli-reference/providers-configure"}]},{"title":"register","url":"/platform/forge/cli-reference/register"},{"title":"settings","url":"/platform/forge/cli-reference/settings","isGroup":true,"groupItems":[{"title":"list","url":"/platform/forge/cli-reference/settings-list"},{"title":"set","url":"/platform/forge/cli-reference/settings-set"}]},{"title":"storage","url":"/platform/forge/cli-reference/storage","isGroup":true,"groupItems":[{"title":"entities","url":"/platform/forge/cli-reference/storage-entities"}]},{"title":"tunnel","url":"/platform/forge/cli-reference/tunnel"},{"title":"uninstall","url":"/platform/forge/cli-reference/uninstall"},{"title":"variables","url":"/platform/forge/cli-reference/variables","isGroup":true,"groupItems":[{"title":"list","url":"/platform/forge/cli-reference/variables-list"},{"title":"set","url":"/platform/forge/cli-reference/variables-set"},{"title":"unset","url":"/platform/forge/cli-reference/variables-unset"}]},{"title":"webtrigger","url":"/platform/forge/cli-reference/webtrigger"},{"title":"whoami","url":"/platform/forge/cli-reference/whoami"}]},{"title":"Manifest","name":"manifest-reference","expandAlways":true,"items":[{"title":"Overview","url":"/platform/forge/manifest-reference/"},{"title":"Action type","url":"/platform/forge/manifest-reference/action-type/"},{"title":"Display conditions","url":"/platform/forge/manifest-reference/display-conditions/","isGroup":true,"groupItems":[{"title":"Usage with Confluence modules","url":"/platform/forge/manifest-reference/display-conditions/confluence/"},{"title":"Usage with Jira modules","url":"/platform/forge/manifest-reference/display-conditions/jira/"},{"title":"Entity property conditions","url":"/platform/forge/manifest-reference/display-conditions/entity-property-conditions/"}]},{"title":"Endpoint","url":"/platform/forge/manifest-reference/endpoint/"},{"title":"Keyboard shortcuts","url":"/platform/forge/manifest-reference/keyboard-shortcuts/"},{"title":"Permissions","url":"/platform/forge/manifest-reference/permissions/","isGroup":true,"groupItems":[{"title":"Forge scopes","url":"/platform/forge/manifest-reference/scopes-forge/"},{"title":"Bitbucket scopes","url":"/platform/forge/manifest-reference/scopes-product-bitbucket/"},{"title":"Compass scopes","url":"/platform/forge/manifest-reference/scopes-product-compass/"},{"title":"Confluence scopes","url":"/platform/forge/manifest-reference/scopes-product-confluence/"},{"title":"Jira scopes","url":"/platform/forge/manifest-reference/scopes-product-jira/"},{"title":"Jira Software scopes","url":"/platform/forge/manifest-reference/scopes-product-jsw/"},{"title":"Jira Service Management scopes","url":"/platform/forge/manifest-reference/scopes-product-jsm/"}]},{"title":"Providers","url":"/platform/forge/manifest-reference/providers/"},{"title":"Remotes","url":"/platform/forge/manifest-reference/remotes/"},{"title":"Resources","url":"/platform/forge/manifest-reference/resources/"},{"title":"Translations","url":"/platform/forge/manifest-reference/translations/","isGroup":true,"groupItems":[{"title":"Forge supported locale codes","url":"/platform/forge/manifest-reference/forge-supported-locale-codes/"}]},{"title":"Variables","url":"/platform/forge/manifest-reference/variables/"}]},{"title":"Modules","name":"modules","expandAlways":true,"items":[{"title":"Overview","url":"/platform/forge/manifest-reference/modules/"},{"title":"Bitbucket modules","url":"/platform/forge/manifest-reference/modules/index-bitbucket/","isGroup":true,"groupItems":[{"title":"Custom merge check","url":"/platform/forge/manifest-reference/modules/bitbucket-merge-check/"},{"title":"Dynamic Pipelines provider","url":"/platform/forge/manifest-reference/modules/bitbucket-dynamic-pipelines-provider/"},{"title":"Repository code overview card","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-code-overview-card/"},{"title":"Repository code overview action","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-code-overview-action/"},{"title":"Repository code overview panel","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-code-overview-panel/"},{"title":"Repository pull request card","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-pull-request-card/"},{"title":"Repository pull request action","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-pull-request-action/"},{"title":"Repository pull request overview panel","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-pull-request-overview-panel/"},{"title":"Repository main menu page","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-main-menu-page/"},{"title":"Repository settings menu page","url":"/platform/forge/manifest-reference/modules/bitbucket-repository-settings-menu-page/"},{"title":"Workspace settings menu page","url":"/platform/forge/manifest-reference/modules/bitbucket-workspace-settings-menu-page/"}]},{"title":"Common modules","url":"/platform/forge/manifest-reference/modules/index-common/","isGroup":true,"groupItems":[{"title":"Consumer","url":"/platform/forge/manifest-reference/modules/consumer/"},{"title":"Function","url":"/platform/forge/manifest-reference/modules/function/"},{"title":"Scheduled trigger","url":"/platform/forge/manifest-reference/modules/scheduled-trigger/"},{"title":"SQL (Preview)","url":"/platform/forge/manifest-reference/modules/sql/"},{"title":"Trigger","url":"/platform/forge/manifest-reference/modules/trigger/"},{"title":"Web trigger","url":"/platform/forge/manifest-reference/modules/web-trigger/"}]},{"title":"Compass modules","url":"/platform/forge/manifest-reference/modules/index-compass/","isGroup":true,"groupItems":[{"title":"Admin page","url":"/platform/forge/manifest-reference/modules/compass-admin-page/"},{"title":"Component page","url":"/platform/forge/manifest-reference/modules/compass-component-page/"},{"title":"Data provider","url":"/platform/forge/manifest-reference/modules/compass-data-provider/"},{"title":"Global page","url":"/platform/forge/manifest-reference/modules/compass-global-page/"},{"title":"Team page","url":"/platform/forge/manifest-reference/modules/compass-team-page/"}]},{"title":"Confluence modules","url":"/platform/forge/manifest-reference/modules/index-confluence/","isGroup":true,"groupItems":[{"title":"Content action","url":"/platform/forge/manifest-reference/modules/confluence-content-action/"},{"title":"Content byline item","url":"/platform/forge/manifest-reference/modules/confluence-content-byline-item/"},{"title":"Context menu","url":"/platform/forge/manifest-reference/modules/confluence-context-menu/"},{"title":"Custom content","url":"/platform/forge/manifest-reference/modules/confluence-custom-content/"},{"title":"Global page","url":"/platform/forge/manifest-reference/modules/confluence-global-page/"},{"title":"Global settings","url":"/platform/forge/manifest-reference/modules/confluence-global-settings/"},{"title":"Homepage feed","url":"/platform/forge/manifest-reference/modules/confluence-homepage-feed/"},{"title":"Space page","url":"/platform/forge/manifest-reference/modules/confluence-space-page/"},{"title":"Space settings","url":"/platform/forge/manifest-reference/modules/confluence-space-settings/"},{"title":"Macro","url":"/platform/forge/manifest-reference/modules/macro/"}]},{"title":"Jira modules","url":"/platform/forge/manifest-reference/modules/index-jira/","isGroup":true,"groupItems":[{"title":"Admin page","url":"/platform/forge/manifest-reference/modules/jira-admin-page/"},{"title":"Backlog action (preview)","url":"/platform/forge/manifest-reference/modules/jira-backlog-action/"},{"title":"Board action (preview)","url":"/platform/forge/manifest-reference/modules/jira-board-action/"},{"title":"Custom field","url":"/platform/forge/manifest-reference/modules/jira-custom-field/"},{"title":"Custom field type","url":"/platform/forge/manifest-reference/modules/jira-custom-field-type/"},{"title":"Dashboard background script","url":"/platform/forge/manifest-reference/modules/jira-dashboard-background-script/"},{"title":"Dashboard gadget","url":"/platform/forge/manifest-reference/modules/jira-dashboard-gadget/"},{"title":"Entity property","url":"/platform/forge/manifest-reference/modules/jira-entity-property/"},{"title":"Global page","url":"/platform/forge/manifest-reference/modules/jira-global-page/"},{"title":"Global permission","url":"/platform/forge/manifest-reference/modules/jira-global-permission/"},{"title":"Issue action","url":"/platform/forge/manifest-reference/modules/jira-issue-action/"},{"title":"Issue activity","url":"/platform/forge/manifest-reference/modules/jira-issue-activity/"},{"title":"Issue context","url":"/platform/forge/manifest-reference/modules/jira-issue-context/"},{"title":"Issue glance","url":"/platform/forge/manifest-reference/modules/jira-issue-glance/"},{"title":"Issue navigator action (preview)","url":"/platform/forge/manifest-reference/modules/jira-issue-navigator-action/"},{"title":"Command palette (preview)","url":"/platform/forge/manifest-reference/modules/jira-command-palette/"},{"title":"Issue panel","url":"/platform/forge/manifest-reference/modules/jira-issue-panel/"},{"title":"Issue view background script","url":"/platform/forge/manifest-reference/modules/jira-issue-view-background-script/"},{"title":"JQL function (preview)","url":"/platform/forge/manifest-reference/modules/jql-function/"},{"title":"Personal settings page (preview)","url":"/platform/forge/manifest-reference/modules/jira-personal-settings-page/"},{"title":"Project page","url":"/platform/forge/manifest-reference/modules/jira-project-page/"},{"title":"Project permission","url":"/platform/forge/manifest-reference/modules/jira-project-permission/"},{"title":"Project settings page","url":"/platform/forge/manifest-reference/modules/jira-project-settings-page/"},{"title":"Sprint action (preview)","url":"/platform/forge/manifest-reference/modules/jira-sprint-action/"},{"title":"Time tracking provider (preview)","url":"/platform/forge/manifest-reference/modules/jira-time-tracking-provider/"},{"title":"UI modifications","url":"/platform/forge/manifest-reference/modules/jira-ui-modifications/"},{"title":"Workflow validator (preview)","url":"/platform/forge/manifest-reference/modules/jira-workflow-validator/"},{"title":"Workflow condition (preview)","url":"/platform/forge/manifest-reference/modules/jira-workflow-condition/"},{"title":"Workflow post function (preview)","url":"/platform/forge/manifest-reference/modules/jira-workflow-post-function/"}]},{"title":"Jira Service Management modules","url":"/platform/forge/manifest-reference/modules/index-jsm/","isGroup":true,"groupItems":[{"title":"Assets Import Type","url":"/platform/forge/manifest-reference/modules/jira-service-management-assets-import-type/"},{"title":"Organization panel","url":"/platform/forge/manifest-reference/modules/jira-service-management-organization-panel/"},{"title":"Portal footer","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-footer/"},{"title":"Portal header","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-header/"},{"title":"Portal profile panel","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-profile-panel/"},{"title":"Portal request create property panel","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-request-create-property-panel/"},{"title":"Portal request detail","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-request-detail/"},{"title":"Portal request detail panel","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-request-detail-panel/"},{"title":"Portal request view action","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-request-view-action/"},{"title":"Portal subheader","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-subheader/"},{"title":"Portal user menu action","url":"/platform/forge/manifest-reference/modules/jira-service-management-portal-user-menu-action/"},{"title":"Queue page","url":"/platform/forge/manifest-reference/modules/jira-service-management-queue-page/"}]},{"title":"Connect module equivalents","url":"/platform/forge/manifest-reference/modules/connect-module-equivalents/"},{"title":"Rovo modules","url":"/platform/forge/manifest-reference/modules/rovo-index/","isGroup":true,"groupItems":[{"title":"Rovo Agent","url":"/platform/forge/manifest-reference/modules/rovo-agent/"},{"title":"Action","url":"/platform/forge/manifest-reference/modules/rovo-action/"}]}]},{"title":"Functions","name":"functions","expandAlways":true,"items":[{"title":"Overview","url":"/platform/forge/function-reference/index/"},{"title":"Arguments","url":"/platform/forge/function-reference/arguments/"},{"title":"Runtimes","url":"/platform/forge/runtime-reference/","isGroup":true,"groupItems":[{"title":"Node.js","url":"/platform/forge/function-reference/nodejs-runtime/"},{"title":"Upgrading from legacy runtime","url":"/platform/forge/runtime-reference/legacy-runtime-migrating/"},{"title":"Legacy runtime (deprecated)","url":"/platform/forge/runtime-reference/legacy-runtime-reference/"}]},{"title":"Forge resolver","url":"/platform/forge/runtime-reference/forge-resolver/"},{"title":"Scheduled triggers","url":"/platform/forge/function-reference/scheduled-trigger/"},{"title":"Web triggers","url":"/platform/forge/runtime-reference/web-trigger/","isGroup":true,"groupItems":[{"title":"Basic usage","url":"/platform/forge/runtime-reference/web-trigger/"},{"title":"Generating a webtrigger URL via SDK","url":"/platform/forge/runtime-reference/web-trigger-api/"}]},{"title":"Async functions","url":"/platform/forge/runtime-reference/async-events-api/","isGroup":true,"groupItems":[{"title":"Basic usage","url":"/platform/forge/runtime-reference/async-events-api/"},{"title":"Error handling","url":"/platform/forge/runtime-reference/async-events-api-error-handling/"}]},{"title":"Product REST APIs","url":"/platform/forge/apis-reference/product-rest-api-reference/","isGroup":true,"groupItems":[{"title":"Bitbucket API requests","url":"/platform/forge/apis-reference/fetch-api-product.requestbitbucket/"},{"title":"Confluence API requests","url":"/platform/forge/apis-reference/fetch-api-product.requestconfluence/"},{"title":"Jira API requests","url":"/platform/forge/apis-reference/fetch-api-product.requestjira/"},{"title":"GraphQL API requests","url":"/platform/forge/apis-reference/fetch-api-product.requestgraph/"}]},{"title":"Fetch APIs","url":"/platform/forge/runtime-reference/fetch-api/","isGroup":true,"groupItems":[{"title":"Basic fetch client","url":"/platform/forge/runtime-reference/fetch-api.basic/"},{"title":"External authentication","url":"/platform/forge/runtime-reference/external-fetch-api/"}]},{"title":"Invoke Remote API","url":"/platform/forge/runtime-reference/invoke-remote-api/"},{"title":"App context API","url":"/platform/forge/runtime-reference/app-context-api/"},{"title":"Privacy API","url":"/platform/forge/runtime-reference/privacy-api/"},{"title":"Authorize API","url":"/platform/forge/runtime-reference/authorize-api/"}]},{"title":"Storage","name":"storage","items":[{"title":"Overview","url":"/platform/forge/runtime-reference/storage-api/"},{"title":"Key-Value Store","url":"/platform/forge/runtime-reference/storage-api-basic/","isGroup":true,"groupItems":[{"title":"Storing data","url":"/platform/forge/runtime-reference/storage-api-basic-api/"},{"title":"Querying data","url":"/platform/forge/runtime-reference/storage-api-query/"},{"title":"Encrypting stored data","url":"/platform/forge/runtime-reference/storage-api-secret/"}]},{"title":"Custom Entity Store","url":"/platform/forge/storage-reference/storage-api-custom-entities/","isGroup":true,"groupItems":[{"title":"Defining entities","url":"/platform/forge/runtime-reference/custom-entities/"},{"title":"Storing entities","url":"/platform/forge/runtime-reference/storage-api-custom-entities/"},{"title":"Querying data","url":"/platform/forge/runtime-reference/storage-api-query-complex/"}]},{"title":"SQL (Preview)","url":"/platform/forge/storage-reference/sql/","isGroup":true,"groupItems":[{"title":"Tutorial","url":"/platform/forge/storage-reference/sql-tutorial/"},{"title":"Manage schemas","url":"/platform/forge/storage-reference/sql-api-schema/"},{"title":"Execute SQL operations","url":"/platform/forge/storage-reference/sql-api/"},{"title":"Error handling","url":"/platform/forge/storage-reference/sql-handling-errors/"}]},{"title":"Cache (EAP)","url":"/platform/forge/storage-reference/storage-cache-api/","isGroup":true,"groupItems":[{"title":"Caching data","url":"/platform/forge/storage-reference/cache/"},{"title":"Error handling","url":"/platform/forge/storage-reference/cache-handling-errors/"}]},{"title":"Object Store (EAP)","url":"/platform/forge/storage-reference/object-store/"}]},{"title":"User Interface","name":"user-interface","expandAlways":true,"items":[{"title":"Overview","url":"/platform/forge/ui-kit/overview/"},{"title":"UI Kit components","url":"/platform/forge/ui-kit/components/","isGroup":true,"groupItems":[{"title":"ADF renderer","url":"/platform/forge/ui-kit/components/adfRenderer/"},{"title":"Badge","url":"/platform/forge/ui-kit/components/badge/"},{"title":"Box","url":"/platform/forge/ui-kit/components/box/"},{"title":"Button","url":"/platform/forge/ui-kit/components/button/"},{"title":"Button group","url":"/platform/forge/ui-kit/components/button-group/"},{"title":"Calendar (Preview)","url":"/platform/forge/ui-kit/components/calendar/"},{"title":"Chart - Bar (EAP)","url":"/platform/forge/ui-kit/components/bar-chart/"},{"title":"Chart - Horizontal bar (EAP)","url":"/platform/forge/ui-kit/components/horizontal-bar-chart/"},{"title":"Chart - Horizontal stack bar (EAP)","url":"/platform/forge/ui-kit/components/horizontal-stack-bar-chart/"},{"title":"Chart - Line (EAP)","url":"/platform/forge/ui-kit/components/line-chart/"},{"title":"Chart - Pie (EAP)","url":"/platform/forge/ui-kit/components/pie-chart/"},{"title":"Chart - Single value (EAP)","url":"/platform/forge/ui-kit/components/single-value-chart/"},{"title":"Chart - Stack bar (EAP)","url":"/platform/forge/ui-kit/components/stack-bar-chart/"},{"title":"Checkbox","url":"/platform/forge/ui-kit/components/checkbox/"},{"title":"Checkbox group (Preview)","url":"/platform/forge/ui-kit/components/checkbox-group/"},{"title":"Code","url":"/platform/forge/ui-kit/components/code/"},{"title":"Code block","url":"/platform/forge/ui-kit/components/code-block/"},{"title":"Date picker","url":"/platform/forge/ui-kit/components/date-picker/"},{"title":"Dynamic table","url":"/platform/forge/ui-kit/components/dynamic-table/"},{"title":"Empty state (Preview)","url":"/platform/forge/ui-kit/components/empty-state/"},{"title":"Form","url":"/platform/forge/ui-kit/components/form/"},{"title":"Frame (Preview)","url":"/platform/forge/ui-kit/components/frame"},{"title":"Heading","url":"/platform/forge/ui-kit/components/heading/"},{"title":"Icon","url":"/platform/forge/ui-kit/components/icon/"},{"title":"Image","url":"/platform/forge/ui-kit/components/image/"},{"title":"Inline","url":"/platform/forge/ui-kit/components/inline/"},{"title":"Inline edit (Preview)","url":"/platform/forge/ui-kit/components/inline-edit/"},{"title":"Link","url":"/platform/forge/ui-kit/components/link/"},{"title":"List (Preview)","url":"/platform/forge/ui-kit/components/list/"},{"title":"Lozenge","url":"/platform/forge/ui-kit/components/lozenge/"},{"title":"Modal","url":"/platform/forge/ui-kit/components/modal/"},{"title":"Popup (Preview)","url":"/platform/forge/ui-kit/components/popup/"},{"title":"Progress bar","url":"/platform/forge/ui-kit/components/progress-bar/"},{"title":"Progress tracker","url":"/platform/forge/ui-kit/components/progress-tracker/"},{"title":"Radio","url":"/platform/forge/ui-kit/components/radio/"},{"title":"Radio group","url":"/platform/forge/ui-kit/components/radio-group/"},{"title":"Range","url":"/platform/forge/ui-kit/components/range/"},{"title":"Section message","url":"/platform/forge/ui-kit/components/section-message/"},{"title":"Select","url":"/platform/forge/ui-kit/components/select/"},{"title":"Spinner","url":"/platform/forge/ui-kit/components/spinner/"},{"title":"Stack","url":"/platform/forge/ui-kit/components/stack/"},{"title":"Tabs","url":"/platform/forge/ui-kit/components/tabs/"},{"title":"Tag","url":"/platform/forge/ui-kit/components/tag/"},{"title":"Tag group","url":"/platform/forge/ui-kit/components/tag-group/"},{"title":"Text","url":"/platform/forge/ui-kit/components/text/"},{"title":"Text area","url":"/platform/forge/ui-kit/components/text-area/"},{"title":"Text field","url":"/platform/forge/ui-kit/components/textfield/"},{"title":"Time picker (Preview)","url":"/platform/forge/ui-kit/components/time-picker/"},{"title":"Toggle","url":"/platform/forge/ui-kit/components/toggle/"},{"title":"Tooltip","url":"/platform/forge/ui-kit/components/tooltip/"},{"title":"User","url":"/platform/forge/ui-kit/components/user/"},{"title":"User group","url":"/platform/forge/ui-kit/components/user-group/"},{"title":"User picker","url":"/platform/forge/ui-kit/components/user-picker/"},{"title":"XCSS","url":"/platform/forge/ui-kit/components/xcss/"}]},{"title":"Jira UI Kit components","url":"/platform/forge/ui-kit/jira-components/","isGroup":true,"groupItems":[{"title":"Custom field edit (Preview)","url":"/platform/forge/ui-kit/jira-components/custom-field-edit/"}]},{"title":"UI Kit hooks","url":"/platform/forge/ui-kit/hooks/hooks-reference/","isGroup":true,"groupItems":[{"title":"useConfig","url":"/platform/forge/ui-kit/hooks/use-config/"},{"title":"useContentProperty","url":"/platform/forge/ui-kit/hooks/use-content-property/"},{"title":"useForm","url":"/platform/forge/ui-kit/hooks/use-form/"},{"title":"useIssueProperty","url":"/platform/forge/ui-kit/hooks/use-issue-property/"},{"title":"useProductContext","url":"/platform/forge/ui-kit/hooks/use-product-context/"},{"title":"useSpaceProperty","url":"/platform/forge/ui-kit/hooks/use-space-property/"},{"title":"useTranslation","url":"/platform/forge/ui-kit/hooks/use-translation/"}]},{"title":"Forge bridge APIs","url":"/platform/forge/apis-reference/ui-api-bridge/bridge","isGroup":true,"groupItems":[{"title":"events","url":"/platform/forge/apis-reference/ui-api-bridge/events/"},{"title":"i18n","url":"/platform/forge/apis-reference/ui-api-bridge/i18n/"},{"title":"invoke","url":"/platform/forge/apis-reference/ui-api-bridge/invoke/"},{"title":"invokeRemote","url":"/platform/forge/apis-reference/ui-api-bridge/invokeRemote/"},{"title":"Modal","url":"/platform/forge/apis-reference/ui-api-bridge/modal/"},{"title":"requestBitbucket","url":"/platform/forge/apis-reference/ui-api-bridge/requestBitbucket/"},{"title":"requestConfluence","url":"/platform/forge/apis-reference/ui-api-bridge/requestConfluence/"},{"title":"requestJira","url":"/platform/forge/apis-reference/ui-api-bridge/requestJira/"},{"title":"router","url":"/platform/forge/apis-reference/ui-api-bridge/router/"},{"title":"showFlag","url":"/platform/forge/apis-reference/ui-api-bridge/showFlag/"},{"title":"view","url":"/platform/forge/apis-reference/ui-api-bridge/view/"}]},{"title":"Jira bridge APIs","url":"/platform/forge/apis-reference/jira-api-bridge/bridge/","isGroup":true,"groupItems":[{"title":"ViewIssueModal","url":"/platform/forge/apis-reference/jira-api-bridge/viewIssueModal/"},{"title":"CreateIssueModal","url":"/platform/forge/apis-reference/jira-api-bridge/createIssueModal/"},{"title":"uiModifications","url":"/platform/forge/apis-reference/jira-api-bridge/uiModifications/"},{"title":"workflowRules (EAP)","url":"/platform/forge/apis-reference/jira-api-bridge/workflowRules/"}]},{"title":"Custom UI","url":"/platform/forge/custom-ui/iframe"},{"title":"Upgrade UI Kit versions","url":"/platform/forge/ui-kit/upgrade-guides","isGroup":true,"groupItems":[{"title":"Upgrade from UI Kit 1 to UI Kit latest version","url":"/platform/forge/ui-kit/upgrade-to-ui-kit-latest/"},{"title":"Notify site admins using Forge app with UI Kit 1","url":"/platform/forge/ui-kit/notify-site-admins-using-forge-app-with-ui-kit-1/"},{"title":"Upgrade to @forge/react major version 10","url":"/platform/forge/ui-kit/version-10-changes/"}]},{"title":"Previous versions","url":"/platform/forge/ui-kit-components/previous_versions","isGroup":true,"groupItems":[{"title":"UI Kit - @forge/react@9","url":"/platform/forge/ui-kit-2/all-uikprev-components/"},{"title":"UI Kit 1 overview","url":"/platform/forge/ui-kit-components/ui1-about/"},{"title":"UI Kit 1 components","url":"/platform/forge/ui-kit-components/uik1_all/"},{"title":"UI Kit 1 module components","url":"/platform/forge/ui-kit-components/uik1_modules/"},{"title":"UI Kit 1 hooks","url":"/platform/forge/ui-kit-components/uik1_hooks/"}]}]},{"title":"Events","name":"events-reference","expandAlways":true,"items":[{"title":"Overview","url":"/platform/forge/events-reference/"},{"title":"Product events","url":"/platform/forge/events-reference/product_events/","isGroup":true,"groupItems":[{"title":"Bitbucket events","url":"/platform/forge/events-reference/bitbucket/"},{"title":"Compass events","url":"/platform/forge/events-reference/compass/"},{"title":"Confluence events","url":"/platform/forge/events-reference/confluence/"},{"title":"Jira events","url":"/platform/forge/events-reference/jira/"},{"title":"Jira Software events","url":"/platform/forge/events-reference/jira-software/"},{"title":"Expressions playground","url":"/platform/forge/events-reference/expressions-playground/"}]},{"title":"Life cycle events","url":"/platform/forge/events-reference/life-cycle/"},{"title":"Data security policy events","url":"/platform/forge/events-reference/data-security-policy-events/"},{"title":"Scheduled trigger events","url":"/platform/forge/events-reference/scheduled-trigger/"},{"title":"Web trigger events","url":"/platform/forge/events-reference/web-trigger/"}]}]},{"title":"Get help","name":"help","url":"/platform/forge/get-help/"},{"name":"changelog","title":"Changelog","url":"/platform/forge/changelog/","apiGroups":["forge-core-platform","forge-jira-cloud-platform","forge-jsm-cloud","forge-jsw-cloud","forge-confluence-cloud"]}],"enabledVersion":"1.5800.1062"},"navigation":[{"label":"About Forge","href":"/platform/forge/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Get started","href":"/platform/forge/introduction/the-forge-platform/","expandState":"always-expanded","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Introduction to Forge","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"The Forge platform","href":"/platform/forge/introduction/the-forge-platform/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Why build with Forge","href":"/platform/forge/introduction/why-build-with-forge/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Migrate your Connect app","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Adopting Forge from Connect","href":"https://developer.atlassian.com/platform/adopting-forge-from-connect/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Learn","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Example apps","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Bitbucket","href":"/platform/forge/example-apps-bitbucket/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Compass","href":"/platform/forge/example-apps-compass/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Confluence","href":"/platform/forge/example-apps-confluence/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Jira","href":"/platform/forge/example-apps-jira/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Jira Service Management","href":"/platform/forge/example-apps-jsm/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Rovo","href":"/platform/forge/example-apps-rovo/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Guided tutorials","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/tutorials-and-guides/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Forge, Compass, and AWS CloudWatch","href":"/platform/forge/forge-compass-cloudwatch/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Schedule web triggers","href":"/platform/forge/add-scheduled-trigger/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Debug functions using IntelliJ","href":"/platform/forge/debug-functions-using-intellij/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Debug functions using VS Code","href":"/platform/forge/debug-functions-using-vscode/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Profile app performance with tunnel debugger","href":"/platform/forge/profiling-node-js-app-code-tunnel/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Implement a dynamic profile retriever","href":"/platform/forge/implement-a-dynamic-profile-retriever-with-external-authentication/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Migrate an app from Connect to Forge","href":"https://developer.atlassian.com/platform/adopting-forge-from-connect/migrate-macro","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Migrate an app from UI Kit 1 to UI Kit","href":"/platform/forge/ui-kit/migration-example/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Set up continuous delivery","href":"/platform/forge/set-up-cicd/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Queue app interactions with Storage API","href":"/platform/forge/storage-api-limit-handling/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use a long-running function","href":"/platform/forge/use-a-long-running-function","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use custom entities to store structured data","href":"/platform/forge/custom-entities-store-structured-data/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use an external OAuth 2.0 API with fetch","href":"/platform/forge/use-an-external-oauth-2.0-api-with-fetch/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Add routing to a full-page app in Jira","href":"/platform/forge/add-routing-to-a-full-page-app/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use the storage API in Confluence","href":"/platform/forge/create-confluence-macro-with-storage-api","expandState":"expanded","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Add custom configuration to a macro","href":"/platform/forge/add-custom-configuration-to-a-macro","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Using rich body macros","href":"/platform/forge/using-rich-text-bodied-macros","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Rovo","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Extend Atlassian products with a Forge Rovo agent","href":"/platform/forge/extend-atlassian-products-with-a-forge-rovo-agent/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Rovo Agent app","href":"/platform/forge/build-a-hello-world-rovo-agent/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Q&A Rovo Agent for Confluence","href":"/platform/forge/build-a-q-and-a-rovo-agent-for-confluence","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Jira issue analyst Rovo Agent","href":"/platform/forge/build-a-jira-issue-analyst-rovo-agent","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Jira","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Build a hello world app in Jira","href":"/platform/forge/build-a-hello-world-app-in-jira/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Automate Jira with triggers","href":"/platform/forge/automate-jira-using-triggers/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Jira comments summarizer app with OpenAI","href":"/platform/forge/build-jira-comments-summarizer-with-openai/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use a workflow validator to check issue assignments","href":"/platform/forge/check-jira-issues-assigned-using-workflow-validator/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a custom UI app","href":"/platform/forge/build-a-custom-ui-app-in-jira/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Jira Service Management","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Build a hello world app in Jira Service Management","href":"/platform/forge/build-a-hello-world-app-in-jira-service-management/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Import third party data into Assets","href":"/platform/forge/assets-import-app/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use Async Events API to queue jobs to import objects into Assets","href":"/platform/forge/queue-events-with-async-events-api-to-import-assets/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a custom UI app","href":"/platform/forge/build-a-custom-ui-app-in-jira-service-management/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Confluence","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Build a hello world app in Confluence","href":"/platform/forge/build-a-hello-world-app-in-confluence/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Create a question generator app in multiple languages using i18n","href":"/platform/forge/create-a-question-generator-app-in-multiple-languages-using-i18n/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Create a quiz app using UI Kit","href":"/platform/forge/create-a-quiz-app-using-ui-kit/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Add configuration to a macro with UI Kit","href":"/platform/forge/add-configuration-to-a-macro-with-ui-kit/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Create a logo designer app using the Frame component (Preview)","href":"/platform/forge/ui-kit/components/frame-tutorial/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use space settings and content byline to implement space news","href":"/platform/forge/space-news/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use content actions to count page macros","href":"/platform/forge/macros-in-the-page/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Custom UI app","href":"/platform/forge/build-a-custom-ui-app-in-confluence/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a Confluence keyword extractor with OpenAI","href":"/platform/forge/build-confluence-keyword-extractor-with-openai/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Use highlighted text in a Confluence app","href":"/platform/forge/create-confluence-contextmenu-module/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Create a GIPHY app using UI kit on Confluence","href":"/platform/forge/create-a-giphy-app-using-the-ui-kit/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Bitbucket","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Extend Bitbucket Cloud","href":"/platform/forge/extend-bitbucket-cloud/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a hello world app in Bitbucket","href":"/platform/forge/build-a-hello-world-app-in-bitbucket/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Automate Bitbucket with triggers","href":"/platform/forge/automate-bitbucket-using-triggers/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build a pull request title validator with custom merge checks","href":"/platform/forge/build-a-pull-request-title-validator-with-custom-merge-checks/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Orchestrate your builds using Dynamic Pipelines","href":"/platform/forge/orchestrate-your-builds-using-dynamic-pipelines/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Atlassian developer glossary","href":"https://developer.atlassian.com/developer-guide/glossary/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Plan & design","href":"/platform/forge/events/","expandState":"always-expanded","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"App architecture","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Events and triggers","href":"/platform/forge/events/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Hosted storage","href":"/platform/forge/storage/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Hosted storage data lifecycle","href":"/platform/forge/storage-reference/hosted-storage-data-lifecycle/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Manifest","href":"/platform/forge/manifest/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Modules","href":"/platform/forge/modules/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Platform quotas and limits","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/platform-quotas-and-limits/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"User interface","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/user-interface/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Build with UI Kit","href":"/platform/forge/ui-kit/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Extend UI with custom options","href":"/platform/forge/extend-ui-with-custom-options/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Design tokens and theming","href":"/platform/forge/design-tokens-and-theming/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Internationalization","href":"/platform/forge/internationalization/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Understanding the UI modifications module","href":"/platform/forge/understanding-ui-modifications/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Jira full page modules","href":"/platform/forge/jira-full-page-modules/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Legal & privacy","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Forge terms of use","href":"/platform/forge/developer-terms/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Shared responsibility model","href":"/platform/forge/shared-responsibility-model/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Forge privacy and security FAQ","href":"/platform/forge/faq-privacy-security/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"User privacy guide","href":"/platform/forge/user-privacy-guidelines/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Forge Data Processing Addendum","href":"/platform/forge/about-the-forge-data-processing-addendum/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Logging data","href":"/platform/forge/logging-guidelines/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Best practice","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"App security","href":"/platform/forge/security/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"App distribution","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Promote an app from staging to production","href":"/platform/forge/staging-and-production-apps/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Distribute via console","href":"/platform/forge/distribute-your-apps/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Build","href":"/platform/forge/getting-started/","expandState":"always-expanded","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Development life cycle","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Developing with Forge","href":"/platform/forge/getting-started/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Environment configuration","href":"/platform/forge/environments-and-versions/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Contributors","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/contributors/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Managing contributors","href":"/platform/forge/manage-app-contributors/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"App versions","href":"/platform/forge/versions/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Testing and debugging","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/debugging/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Debug using IntelliJ","href":"/platform/forge/debug-functions-using-intellij/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Debug using VS Code","href":"/platform/forge/debug-functions-using-vscode/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Tunneling","href":"/platform/forge/tunneling/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"App capabilities","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Compute","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Functions","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Invoke functions","href":"/platform/forge/function-reference/index/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call a product REST API","href":"/platform/forge/apis-reference/product-rest-api-reference/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call a product GraphQL API","href":"/platform/forge/apis-reference/fetch-api-product.requestgraph/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Verify user permissions for product APIs","href":"/platform/forge/runtime-reference/authorize-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call an external REST API","href":"/platform/forge/runtime-reference/external-fetch-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Check user account status","href":"/platform/forge/runtime-reference/authorize-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Migrate from the legacy runtime","href":"/platform/forge/runtime-reference/legacy-runtime-migrating/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Remotes","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/remote/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Forge remote essentials","href":"/platform/forge/remote/essentials/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Send events to a remote","href":"/platform/forge/remote/sending-product-events/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Schedule triggers to invoke a remote","href":"/platform/forge/remote/scheduled-triggers/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Access Forge storage from a remote","href":"/platform/forge/remote/accessing-storage/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call product APIs from a remote","href":"/platform/forge/remote/calling-product-apis/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call from a Forge frontend","href":"/platform/forge/remote/calling-from-frontend/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Call from a Forge function","href":"/platform/forge/remote/calling-from-function/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Bitbucket git operations from a remote","href":"/platform/forge/remote/bitbucket-git-operations/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Remote observability","href":"/platform/forge/remote/observability/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Setting up remotes for realm pinning","href":"/platform/forge/remote/setup-dare-storage/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Web triggers","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Work with web triggers","href":"/platform/forge/runtime-reference/web-trigger/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Queues","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Use async app event queues","href":"/platform/forge/runtime-reference/async-events-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Events","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Platform and product events","href":"/platform/forge/events/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Reference","href":"/platform/forge/function-reference/index/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Storage","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Key value store","href":"/platform/forge/runtime-reference/storage-api-basic/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Entity store","href":"/platform/forge/storage-reference/storage-api-custom-entities/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"SQL (Preview)","href":"/platform/forge/storage-reference/sql/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Cache (EAP)","href":"/platform/forge/storage-reference/storage-cache-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Reference","href":"/platform/forge/runtime-reference/storage-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Hosted storage data lifecycle","href":"/platform/forge/storage-reference/hosted-storage-data-lifecycle/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"User interface","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"UI Kit","href":"/platform/forge/ui-kit/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Frontend bridge","href":"/platform/forge/apis-reference/ui-api-bridge/bridge/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Display conditions","href":"/platform/forge/manifest-reference/display-conditions/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Reference","href":"/platform/forge/ui-kit/overview/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Observability","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/remote/observability/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"App observability in third-party tools","href":"/platform/forge/app-observability-in-third-party-tools","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Automation with Forge","href":"/platform/forge/automation-with-forge/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Trust and security","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Data residency","href":"/platform/forge/data-residency/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Configuring app security","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Unlicensed user app access","href":"/platform/forge/access-to-forge-apps-for-unlicensed-jsm-users/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Scopes to call an Atlassian REST API","href":"/platform/forge/add-scopes-to-call-an-atlassian-rest-api/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Runtime egress permissions","href":"/platform/forge/runtime-egress-permissions/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Content security and egress controls","href":"/platform/forge/add-content-security-and-egress-controls/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"App context security","href":"/platform/forge/app-context-security/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"External authentication overview","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Configuring OAuth 2.0 providers","href":"/platform/forge/use-an-external-oauth-2.0-api-with-fetch/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Rotating an OAuth 2.0 client ID and secret","href":"/platform/forge/rotating-an-oauth-2.0-client-id-and-secret/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Common issues with external authentication","href":"/platform/forge/common-issues-with-external-authentication/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Runs on Atlassian","href":"/platform/forge/runs-on-atlassian/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Enterprise development","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Using Forge CLI on a corporate network","href":"/platform/forge/enterprise/use-forge-cli-on-corporate-network/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Forge releases and deprecation policy","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Forge releases (includes enrolling in EAP)","href":"/platform/forge/whats-coming/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Forge deprecation policy","href":"/platform/forge/deprecation-policy/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Manage","href":"/platform/forge/manage-your-apps/","expandState":"always-expanded","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/manage-your-apps/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Observability","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Manage app alerts","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/alerts/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Create alert rules","href":"/platform/forge/create-alert-rules/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Manage alert rules","href":"/platform/forge/manage-alert-rules/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"View open and closed alerts","href":"/platform/forge/view-open-and-closed-alerts/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Monitor app metrics","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/monitor-app-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Monitor invocation metrics","href":"/platform/forge/monitor-invocation-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Monitor API metrics","href":"/platform/forge/monitor-api-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Monitor cache metrics (EAP)","href":"/platform/forge/monitor-cache-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Monitor SQL (Preview)","href":"/platform/forge/monitor-sql-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Monitor usage metrics","href":"/platform/forge/monitor-usage-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Export app metrics","href":"/platform/forge/export-app-metrics/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Monitor app logs","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Overview","href":"/platform/forge/monitor-app-logs/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"View app logs","href":"/platform/forge/view-app-logs/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Export app logs","href":"/platform/forge/export-app-logs/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Access app logs","href":"/platform/forge/access-app-logs/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"View app installations","href":"/platform/forge/view-app-installations/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"View app storage","href":"/platform/forge/view-app-storage/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]},{"label":"Access","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Manage app contributors","href":"/platform/forge/manage-app-contributors/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Manage environments","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Forge environments","href":"/platform/forge/environments-and-versions/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Configuring the manifest","href":"/platform/forge/manifest-reference/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]},{"label":"Distribution","href":"","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[{"label":"Marketplace","href":"https://developer.atlassian.com/platform/marketplace/listing-forge-apps/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"Distribute via console","href":"/platform/forge/distribute-your-apps/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]},{"label":"CLI installation","href":"/platform/forge/cli-reference/install/","expandState":"collapsed","childNavigationNodes":[],"nestedNavigationNodes":[]}]}]}],"theme":"grouped-sidebar","newRestApiExperience":true},"frontEndFeatures":{"shouldShowDacIntercept":true,"shouldShowGetHelpWidget":true,"renderRestRedesignedDocs":{"contentSets":[],"enableAllInternal":true,"enableAllExternal":true},"targetExternalBuilders":{"contentSets":[],"userEmails":[]},"shouldEnableAIfeatures":false},"getHelpBaseUrl":"https://dac-get-help.services.atlassian.com","changelogStargateBaseUrl":"/gateway/api/dac-changelogs","bitbucketClientId":"wuJ9hf4zyXjYJVxWFf","isContentSetInternal":false};</script> <title>Use the Forge hosted storage in a Confluence macro</title> <style data-styled-components="bcCCNc jqBRrP ibwhYF eZnlXi bsbZCT cEicjz hEREHr cWyolX ccUuQb KLVHW RfwMt ebpAmp dEUQgS jgvUXc cEunxv jGeTgW hSXbpc fFirge hKiNSh iuGVGX bCtJbM hwrSXl iARtDw BlNLE iLnIWi eGFUop fdZVrh ixXsyz hMVyQH ebjqXf jOJzhX gupbxx iJfdrZ dZmoXu EsMfL gjDNHe fEiqUH hiBcEo jjvRrZ kFokHU kyARPC kKjlYb dDqXHW cRavQB gWIkLp jGqvBW hsaQyA bWkibq huMuzN hYifdp crKIBs bIjwqY iLIKSx eysgIS cLWHVF cQNBrn jCVVco fypsmc jgxetf vudGk kiIrR rJVhP hrxrbx gfLKuW kmRqgF APFeF hbQcmX dUcFyG RSHIw insOyI fDSCxc"> /* sc-component-id: sc-keyframes-bcCCNc */ @-webkit-keyframes bcCCNc{0%{opacity:0;}100%{opacity:1;}} @keyframes bcCCNc{0%{opacity:0;}100%{opacity:1;}} /* sc-component-id: sc-keyframes-jqBRrP */ @-webkit-keyframes jqBRrP{0%{opacity:1;}50%{opacity:0.6;}100%{opacity:1;}} @keyframes jqBRrP{0%{opacity:1;}50%{opacity:0.6;}100%{opacity:1;}} /* sc-component-id: sc-keyframes-ibwhYF */ @-webkit-keyframes ibwhYF{to{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);}} @keyframes ibwhYF{to{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);}} /* sc-component-id: sc-cZBZkQ */ .fypsmc{position:relative;} .fypsmc:not(:hover):not(:focus-within) .copy{position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden;} /* sc-component-id: sc-gbzWSY */ .jgxetf{position:relative;top:var(--ds-space-0,0px);left:var(--ds-space-0,0px);width:100%;z-index:0;} /* sc-component-id: sc-jqIZGH */ .vudGk{border-radius:3px;background-color:#f4f5f7;color:#172b4d;font-size:12px;line-height:20px;overflow:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;} .vudGk pre{margin:var(--ds-space-0,0px);padding:var(--ds-space-100,8px);} .vudGk pre:first-child{float:left;text-align:right;background-color:#ebecf0;color:#8993a4;font-size:14px;} .vudGk code{display:inline-block;position:relative;left:var(--ds-space-200,16px);padding-right:var(--ds-space-200,16px);} /* sc-component-id: sc-jGxEUC */ .jCVVco{margin:16px var(--ds-space-0,0px);padding:var(--ds-space-0,0px);max-height:500px;overflow:auto;} /* sc-component-id: sc-jdeSqf */ .cQNBrn{overflow-wrap:break-word;word-wrap:break-word;} /* sc-component-id: sc-cBrjTV */ .crKIBs{padding-top:var(--ds-space-300,24px);} .crKIBs:first-child{padding-top:var(--ds-space-0,0px);} .crKIBs h1 .heading-anchor-wrapper{position:absolute;height:1.1666666666666667em;margin-left:var(--ds-space-075,6px);} .crKIBs h1 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h1 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h1:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} .crKIBs h2 .heading-anchor-wrapper{position:absolute;height:1.2em;margin-left:var(--ds-space-075,6px);} .crKIBs h2 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h2 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h2:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} .crKIBs h3 .heading-anchor-wrapper{position:absolute;height:1.25em;margin-left:var(--ds-space-075,6px);} .crKIBs h3 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h3 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h3:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} .crKIBs h4 .heading-anchor-wrapper{position:absolute;height:1.1428571428571428em;margin-left:var(--ds-space-075,6px);} .crKIBs h4 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h4 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h4:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} .crKIBs h5 .heading-anchor-wrapper{position:absolute;height:1.3333333333333333em;margin-left:var(--ds-space-075,6px);} .crKIBs h5 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h5 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h5:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} .crKIBs h6 .heading-anchor-wrapper{position:absolute;height:1.4545454545454546em;margin-left:var(--ds-space-075,6px);} .crKIBs h6 .heading-anchor-wrapper button{padding-left:var(--ds-space-0,0px);padding-right:var(--ds-space-0,0px);} @media (hover:hover) and (pointer:fine){.crKIBs h6 .heading-anchor-wrapper > button{opacity:0;-webkit-transform:translate(-8px,0px);-ms-transform:translate(-8px,0px);transform:translate(-8px,0px);-webkit-transition:opacity 0.2s ease 0s,-webkit-transform 0.2s ease 0s;-webkit-transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;transition:opacity 0.2s ease 0s,transform 0.2s ease 0s;}.crKIBs h6:hover .heading-anchor-wrapper > button{opacity:1;-webkit-transform:none !important;-ms-transform:none !important;transform:none !important;}} /* sc-component-id: sc-iCwjlJ */ .bIjwqY{display:inline;outline:none;background-color:transparent;border:none;color:#42526E;cursor:pointer;right:var(--ds-space-0,0px);} /* sc-component-id: sc-fkyLDJ */ .jGeTgW{min-height:100vh;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;} /* sc-component-id: sc-jUpvKA */ .kmRqgF{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;} /* sc-component-id: sc-cmIlrE */ .kiIrR{cursor:pointer;} /* sc-component-id: sc-eNPDpu */ .iARtDw{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:fixed;bottom:var(--ds-space-400,32px);left:var(--ds-space-400,32px);z-index:1;} /* sc-component-id: sc-hARARD */ .hrxrbx{text-align:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin-left:16px;margin-top:var(--ds-space-500,40px);margin-bottom:var(--ds-space-500,40px);} /* sc-component-id: sc-ccLTTT */ .gfLKuW{font-size:14px;color:#6B778C;margin:var(--ds-space-0,0px) var(--ds-space-050,4px) var(--ds-space-0,0px) var(--ds-space-0,0px);} /* sc-component-id: sc-TuwoP */ .hKiNSh{max-height:100px;background-color:#DEEBFF;} /* sc-component-id: sc-fQkuQJ */ .iuGVGX{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#DEEBFF;color:#172B4D;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;fill:#DEEBFF;font-weight:600;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding:12px;text-align:center;margin:auto;max-width:876px;} /* sc-component-id: sc-epGmkI */ .bCtJbM{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;} /* sc-component-id: sc-dphlzf */ .fFirge{max-height:0px;overflow:hidden;-webkit-transition:max-height 0.25s ease-in-out;transition:max-height 0.25s ease-in-out;} /* sc-component-id: sc-fCPvlr */ .hwrSXl{-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;padding:4px;overflow:hidden;} /* sc-component-id: sc-gAmQfK */ .hSXbpc{color:black;position:relative;z-index:100;} .hSXbpc div[data-testid='navigation-site-title']{color:#172B4D;font-size:16px;} /* sc-component-id: sc-hvvHee */ .APFeF{margin-top:var(--ds-space-400,32px) padding:var(--ds-space-200,16px) var(--ds-space-100,8px);background:#F4F5F7;color:white;min-height:100px;} .APFeF,.APFeF *{box-sizing:border-box;} @media (min-width:768px){.APFeF{padding:var(--ds-space-400,32px) var(--ds-space-100,8px);}} /* sc-component-id: sc-eSePXt */ .hbQcmX{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;max-width:80rem;margin-left:auto;margin-right:auto;padding-left:0.9375rem;padding-right:0.9375rem;} @media (min-width:860px){.hbQcmX{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}} /* sc-component-id: sc-dXfzlN */ .insOyI{-webkit-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;} @media (min-width:860px){.insOyI{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}} @media (max-width:1024px){.insOyI{font-size:14px;}} /* sc-component-id: sc-aewfc */ .fDSCxc{color:#0a0a0a;display:inline-block;line-height:1;padding:var(--ds-space-150,12px) var(--ds-space-400,32px) var(--ds-space-150,12px) var(--ds-space-0,0px);} @media (min-width:768px){.fDSCxc{padding:var(--ds-space-150,12px) var(--ds-space-200,16px);}} @media (max-width:1024px){.fDSCxc{font-size:14px;}} /* sc-component-id: sc-iIHjhz */ .RSHIw{color:#0057d8;display:inline-block;line-height:1;padding:var(--ds-space-150,12px) var(--ds-space-400,32px) var(--ds-space-150,12px) var(--ds-space-0,0px);} @media (min-width:768px){.RSHIw{padding:var(--ds-space-150,12px) var(--ds-space-200,16px);}} .RSHIw.hide-optanon-link{display:none;} /* sc-component-id: sc-eQGPmX */ .ebjqXf a[type='button']{line-height:18px;height:auto;padding:var(--ds-space-0,0px);text-align:left;} /* sc-component-id: sc-dAOnuy */ .gupbxx{white-space:normal;} /* sc-component-id: sc-cSYcjD */ .EsMfL{height:auto;list-style:none;margin:var(--ds-space-0,0px);overflow:hidden;padding:var(--ds-space-0,0px);} .EsMfL.EsMfL{margin-top:var(--ds-space-0,0px);}.gjDNHe{height:0;list-style:none;margin:var(--ds-space-0,0px);overflow:hidden;padding:var(--ds-space-0,0px);} .gjDNHe.gjDNHe{margin-top:var(--ds-space-0,0px);} /* sc-component-id: sc-gjAXCV */ .fEiqUH{width:200px;white-space:normal;overflow-wrap:break-word;word-wrap:break-word;min-height:24px !important;padding:4px 0px 4px 4px !important;} .fEiqUH > span:first-child{margin-right:4px;}.hiBcEo{width:200px;white-space:normal;overflow-wrap:break-word;word-wrap:break-word;min-height:24px !important;padding:4px 0px 4px 30px !important;} .hiBcEo > span:first-child{margin-right:4px;}.jjvRrZ{width:200px;white-space:normal;overflow-wrap:break-word;word-wrap:break-word;min-height:24px !important;padding:4px 0px 4px 56px !important;} .jjvRrZ > span:first-child{margin-right:4px;} /* sc-component-id: sc-dOkuiw */ .kFokHU{min-height:32px !important;font-size:14px;font-weight:400;line-height:20px;text-align:left;border-radius:4px;padding:4px 0px 4px 58px !important;}.kyARPC{min-height:32px !important;font-size:14px;font-weight:400;line-height:20px;text-align:left;border-radius:4px;padding:4px 0px 4px 84px !important;}.kKjlYb{min-height:32px !important;font-size:14px;font-weight:400;line-height:20px;text-align:left;border-radius:4px;padding:4px 0px 4px 110px !important;}.dDqXHW{min-height:32px !important;font-size:14px;font-weight:400;line-height:20px;text-align:left;border-radius:4px;padding:4px 0px 4px 32px !important;} /* sc-component-id: sc-jGFFOr */ .iJfdrZ{border-top:1px solid #EBECF0;margin:var(--ds-space-0,0px);padding:16px 0;margin-left:var(--ds-space-150,12px);position:relative;} .iJfdrZ:last-child{border-bottom:1px solid #EBECF0;} /* sc-component-id: sc-hZeNU */ .dZmoXu{color:#253858;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;font-weight:var(--ds-font-heading-large,700);line-height:22px;display:'flex';} /* sc-component-id: sc-hMjcWo */ .jOJzhX{padding:4px var(--ds-space-0,0px) 2px;} .jOJzhX > a[type='button']{font-weight:inherit;color:inherit;} .jOJzhX > a[type='button']:before{content:" ";display:inline-block;line-height:18px;min-width:0.5rem;} .jOJzhX > a[type='button']:hover{background-color:inherit;color:rgb(0,82,204) !important;} /* sc-component-id: sc-dBfaGr */ .hMVyQH{list-style:none;margin:var(--ds-space-0,0px);padding:var(--ds-space-0,0px);} /* sc-component-id: sc-jgVwMx */ .ixXsyz{padding:16px 0;} /* sc-component-id: sc-giOsra */ .cEicjz{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-radius:3px;background-color:#DEEBFF;padding:16px;}.hEREHr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-radius:3px;background-color:#FFFAE6;padding:16px;}.cWyolX{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-radius:3px;background-color:#E3FCEF;padding:16px;} /* sc-component-id: sc-SFOxd */ .KLVHW{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;} /* sc-component-id: sc-jOBXIr */ .ebpAmp{margin:0;font-size:1.1428571428571428em;font-style:inherit;line-height:1.25;color:#172B4D;font-weight:600;-webkit-letter-spacing:-0.006em;-moz-letter-spacing:-0.006em;-ms-letter-spacing:-0.006em;letter-spacing:-0.006em;margin-top:24px;} /* sc-component-id: sc-dzOgQY */ * + .RfwMt{margin-top:8px;} /* sc-component-id: sc-jOVcOr */ .ccUuQb{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:40px;} .ccUuQb > span{margin:-2px 0;vertical-align:top;} /* sc-component-id: sc-hkaZBZ */ .bsbZCT{margin:16px var(--ds-space-0,0px);} .bsbZCT > section > div:last-child{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;overflow-x:auto;} /* sc-component-id: sc-gLdKKF */ .dEUQgS{position:relative;padding-top:56.25%;margin:16px var(--ds-space-0,0px);height:0;overflow:hidden;max-width:100%;} /* sc-component-id: sc-gCUMDz */ .jgvUXc{position:absolute;top:var(--ds-space-0,0px);left:var(--ds-space-0,0px);width:100%;height:100%;} /* sc-component-id: sc-grYksN */ .jGqvBW{display:none;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin:var(--ds-space-0,0px) 15px;} @media (min-width:600px){.jGqvBW{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-top:20px;}} /* sc-component-id: sc-frudsx */ .hsaQyA{display:none;} @media (min-width:900px){.hsaQyA{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;color:#6B778C;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}} /* sc-component-id: sc-cBXKeB */ .bWkibq{display:none;padding-right:4px;} @media (min-width:1200px){.bWkibq{display:initial;}} /* sc-component-id: sc-fjNYmT */ .cRavQB{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:3;-webkit-flex-grow:3;-ms-flex-positive:3;flex-grow:3;margin:var(--ds-space-0,0px) auto;max-width:1200px;padding:var(--ds-space-0,0px) var(--ds-space-400,32px);} @media (min-width:900px){.cRavQB{overflow:visible;}} /* sc-component-id: sc-hzOKmB */ .gWIkLp{display:block;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin-top:var(--ds-space-0,0px)px;} @media (min-width:900px){.gWIkLp{margin-right:192px;}} /* sc-component-id: sc-jBoNkH */ .eGFUop{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column-reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;width:100%;} @media (min-width:900px){.eGFUop{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}} /* sc-component-id: sc-fPbjcq */ .fdZVrh{box-sizing:border-box;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;max-width:350px;width:20%;border-right:1px solid rgba(9,30,66,0.08);display:none;padding:8px 16px 32px 16px;} @media (min-width:900px){.fdZVrh{display:block;}} /* sc-component-id: sc-hdNmWC */ .huMuzN{-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:3;-webkit-flex-grow:3;-ms-flex-positive:3;flex-grow:3;margin:15px;margin-top:8px;width:80%;} /* sc-component-id: sc-hBcjXN */ .iLnIWi{-webkit-flex:1 0 auto;-ms-flex:1 0 auto;flex:1 0 auto;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;} .iLnIWi h1 + h2{margin-top:12px;} .iLnIWi h1 + h3{margin-top:16px;} /* sc-component-id: sc-gVZiCL */ .BlNLE img{max-width:100%;} .BlNLE tr{border-bottom:1px solid #C1C7D0;} .BlNLE thead{border-bottom:none;} .BlNLE th{background-color:#F4F5F7;padding:8px;} .BlNLE td{padding:8px;} .BlNLE .aui-lozenge{background:#42526E;border:0;border-radius:3px;color:#FFFFFF;box-sizing:border-box;display:inline-block;font-size:11px;font-weight:700;line-height:1;max-width:200px;padding:var(--ds-space-025,2px) var(--ds-space-050,4px) var(--ds-space-025,2px);text-transform:uppercase;vertical-align:baseline;} .BlNLE .aui-lozenge-subtle{background-color:#DFE1E6;color:#42526E;} .BlNLE .aui-lozenge-success{background-color:#00875A;color:#FFFFFF;} .BlNLE .aui-lozenge-error,.BlNLE .aui-lozenge-removed{background-color:#BF2600;color:#FFFFFF;} .BlNLE .aui-lozenge-inprogress{background-color:#0052CC;color:#FFFFFF;} .BlNLE .aui-lozenge-new{background-color:#5243AA;color:#FFFFFF;} .BlNLE .aui-lozenge-moved{background-color:#FF991F;color:#172B4D;} .BlNLE .aui-lozenge-current{background-color:#FFC400;color:#42526E;} .BlNLE .aui-lozenge-complete{background-color:#5E6C84;color:#FFFFFF;} .BlNLE .aui-lozenge-success.aui-lozenge-subtle{background-color:#E3FCEF;color:#006644;} .BlNLE .aui-lozenge-error.aui-lozenge-subtle,.BlNLE .aui-lozenge-removed.aui-lozenge-subtle{background-color:#FFEBE6;color:#BF2600;} .BlNLE .aui-lozenge-current.aui-lozenge-subtle,.BlNLE .aui-lozenge-inprogress.aui-lozenge-subtle{background-color:#DEEBFF;color:#0747A6;} .BlNLE .aui-lozenge-complete.aui-lozenge-subtle,.BlNLE .aui-lozenge-new.aui-lozenge-subtle{background-color:#EAE6FF;color:#403294;} .BlNLE .aui-lozenge-moved.aui-lozenge-subtle{background-color:#FFF0B3;color:#172B4D;} .BlNLE .aui-message{position:relative;margin:16px var(--ds-space-0,0px);border-radius:3px;padding:16px;padding-left:56px;} .BlNLE .aui-message p strong,.BlNLE .aui-message p.title{font-size:1.1428571428571428em;font-style:inherit;line-height:1.25;color:#172B4D;font-weight:600;-webkit-letter-spacing:-0.006em;-moz-letter-spacing:-0.006em;-ms-letter-spacing:-0.006em;letter-spacing:-0.006em;margin-top:24px;font-size:16px;margin-top:var(--ds-space-0,0px);} .BlNLE .aui-message p.title{margin-bottom:8px;} .BlNLE .aui-message p.title + p{margin-top:var(--ds-space-0,0px);} .BlNLE .aui-message.tip{background-color:#E3FCEF;} .BlNLE .aui-message.note,.BlNLE .aui-message.info{background-color:#DEEBFF;} .BlNLE .aui-message.warning{background-color:#FFFAE6;} .BlNLE .aui-message-tip{background-color:#E3FCEF;} .BlNLE .aui-message-note,.BlNLE .aui-message-tip{background-color:#DEEBFF;} .BlNLE .aui-message-warning{background-color:#FFFAE6;} .BlNLE blockquote{padding:8px 16px var(--ds-space-0,0px) 16px;border-left:1px solid #C1C7D0;margin:var(--ds-space-0,0px) var(--ds-space-0,0px) 16px;color:#97A0AF;} .BlNLE blockquote:after,.BlNLE blockquote:before{content:'';} /* sc-component-id: sc-imDdex */ @media (min-width:900px){.hYifdp{position:relative;margin-right:192px;}} /* sc-component-id: sc-lffWgi */ @media (min-width:900px){.iLIKSx{position:absolute;left:100%;height:100%;margin-top:12px;}} /* sc-component-id: sc-fGSyRc */ .eysgIS{border-left:4px solid #0052CC;padding:8px;margin:30px var(--ds-space-0,0px);} .eysgIS:empty{display:none;} .eysgIS > :first-child{margin-bottom:32px;} @media (min-width:900px){.eysgIS{position:-webkit-sticky;position:sticky;top:82px;border-left:none;margin:var(--ds-space-0,0px);padding:var(--ds-space-0,0px);box-sizing:border-box;width:192px;}} /* sc-component-id: sc-dCVVYJ */ .rJVhP{display:'flex';-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;} /* sc-component-id: sc-jkPxnQ */ .cLWHVF{padding-left:28px;} /* sc-component-id: sc-cyQzhP */ .cEunxv{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;} /* sc-component-id: sc-keyframes-eZnlXi */ @-webkit-keyframes eZnlXi{from{opacity:0;-webkit-transform:translateY(-10px);-ms-transform:translateY(-10px);transform:translateY(-10px);}to{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);}} @keyframes eZnlXi{from{opacity:0;-webkit-transform:translateY(-10px);-ms-transform:translateY(-10px);transform:translateY(-10px);}to{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);}} /* sc-component-id: sc-global-2906074290 */ @font-face{font-family:'Charlie Display';font-weight:400;src:url('/font/charlie-display/CharlieDisplay-Regular.otf') format('opentype');} @font-face{font-family:'Charlie Display';font-weight:500;src:url('/font/charlie-display/CharlieDisplay-Semibold.otf') format('opentype');} /* sc-component-id: sc-global-4218966353 */ *{box-sizing:border-box;}</style> <link href="https://dac-static.atlassian.com/_static/documentation-changelogs-docs-index-rest-api-docs-rest-docs-search-graphql-docs-graphql-sandbox-jsapi-connect-module-pages-analytics-and-cookie-preferences-homepage-errors-supportdesk.dfe18eccc22cf5b32118.chunk.css" rel="stylesheet"><link href="https://dac-static.atlassian.com/_static/documentation-changelogs-docs-index-rest-api-docs-rest-docs-search-graphql-docs-graphql-sandbox-jsapi-connect-module-pages-homepage-errors-supportdesk.c67a7555063c3b00faae.chunk.css" rel="stylesheet"><link href="https://dac-static.atlassian.com/_static/documentation.ce5deedee0b24a12eac1.css" rel="stylesheet"> <!-- Algolia Search Insights --> <script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8="> const ALGOLIA_INSIGHTS_SRC = "https://cdn.jsdelivr.net/npm/search-insights@2.2.1"; window.ALGOLIA_DAC_INDEX_NAME = 'developer.atlassian.com-dac-prod'; window.ALGOLIA_DAC_APP_ID = '41O4X7L3MX'; !function(e,a,t,n,s,i,c){e.AlgoliaAnalyticsObject=s,e[s]=e[s]||function(){ (e[s].queue=e[s].queue||[]).push(arguments)},i=a.createElement(t),c=a.getElementsByTagName(t)[0], i.async=1,i.src=n,c.parentNode.insertBefore(i,c) }(window,document,"script",ALGOLIA_INSIGHTS_SRC,"algoliaAnalytics"); algoliaAnalytics('init', { appId: '41O4X7L3MX', apiKey: 'Y2ZkNTM4MDg5M2QyMDUzOTBlMGEwZTU5OGQ0NGQ1MTA0ZmM1MjM5NzUzODdjNDZmYTRjYzkwMGFlYmIwMDE0MnJlc3RyaWN0SW5kaWNlcz1kZXZlbG9wZXIuYXRsYXNzaWFuLmNvbS1kYWMtcHJvZCUyQ2RldmVsb3Blci5hdGxhc3NpYW4uY29tLWRhYy1zdGFnaW5nJTJDZGV2ZWxvcGVyLmF0bGFzc2lhbi5jb20tZGFjLWRldiZmaWx0ZXJzPXByaXZpbGVnZSUzQU5PTkU=', useCookie: true, }); </script> <!-- End Algolia Search Insights --> <script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8="> window.ALGOLIA_DAC_API_KEY = 'Y2ZkNTM4MDg5M2QyMDUzOTBlMGEwZTU5OGQ0NGQ1MTA0ZmM1MjM5NzUzODdjNDZmYTRjYzkwMGFlYmIwMDE0MnJlc3RyaWN0SW5kaWNlcz1kZXZlbG9wZXIuYXRsYXNzaWFuLmNvbS1kYWMtcHJvZCUyQ2RldmVsb3Blci5hdGxhc3NpYW4uY29tLWRhYy1zdGFnaW5nJTJDZGV2ZWxvcGVyLmF0bGFzc2lhbi5jb20tZGFjLWRldiZmaWx0ZXJzPXByaXZpbGVnZSUzQU5PTkU='; window.ALGOLIA_DAC_API_KEY_EXPIRY = Date.now() + 28800000; window.ENABLE_AI = false; </script><script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8="> window.visualEditorEnabled = 'true'; </script><script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8="> window.DAC_CDN_HOST = 'https://dac-static.atlassian.com'; window.ENABLED_VERSION = '1.5800.1062'; </script></head> <body> <div id="root"><div class="sc-cyQzhP cEunxv"><div class="sc-fkyLDJ jGeTgW"><div><div class="sc-gAmQfK hSXbpc"><div class="sc-dphlzf fFirge"><div class="sc-TuwoP hKiNSh" aria-hidden="true" data-testid="banner-container" role="alert"><div class="sc-fQkuQJ iuGVGX"><span class="sc-epGmkI bCtJbM"><style data-emotion-css="14fi9av">.css-14fi9av{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-weight:500;max-width:100%;outline:none !important;text-align:center;-webkit-text-decoration:none;text-decoration:none;white-space:nowrap;background:none;border-radius:3px;box-shadow:0 0 0 2px inherit;color:#42526E !important;cursor:default;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 8px;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);-webkit-transition-duration:0.1s,0.15s;transition-duration:0.1s,0.15s;vertical-align:middle;width:auto;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;}.css-14fi9av::-moz-focus-inner{border:0;margin:0;padding:0;}.css-14fi9av:hover{-webkit-text-decoration:inherit;text-decoration:inherit;}</style><button aria-label="close-icon" type="button" class="css-14fi9av"><style data-emotion-css="j8fq0c">.css-j8fq0c{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%;position:relative;}</style><span class="css-j8fq0c"><style data-emotion-css="noix33">.css-noix33{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:0;font-size:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;margin:0 -2px;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;opacity:1;}</style><span class="css-noix33"><style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="close-icon" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 10.586L6.707 5.293a1 1 0 00-1.414 1.414L10.586 12l-5.293 5.293a1 1 0 001.414 1.414L12 13.414l5.293 5.293a1 1 0 001.414-1.414L13.414 12l5.293-5.293a1 1 0 10-1.414-1.414L12 10.586z" fill="currentColor"/></svg></span></span></span></button></span><span class="sc-fCPvlr hwrSXl"><span></span></span></div></div></div><style data-emotion-css="1cychdt">.css-1cychdt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;height:56px;padding-right:12px;padding-left:12px;position:relative;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}[data-theme="light"] .css-1cychdt,[data-theme="dark"] .css-1cychdt{border-bottom:1px solid var(--ds-border,#091E4224);}[data-theme="light"] .css-1cychdt::after,[data-theme="dark"] .css-1cychdt::after{content:none;}.css-1cychdt::after{height:4px;position:absolute;top:100%;right:0;left:0;background:linear-gradient(180deg,rgba(9,30,66,0.13) 0,rgba(9,30,66,0.13) 1px,rgba(9,30,66,0.08) 1px,rgba(9,30,66,0) 4px);content:"";}</style><header style="background-color:var(--ds-surface, #FFFFFF);color:var(--ds-text-subtlest, #6B778C)" role="banner" class="css-1cychdt"><style data-emotion-css="vtikxo">.css-vtikxo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;height:inherit;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}.css-vtikxo > *{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><nav aria-label="Atlassian Developer Navigation" class="css-vtikxo"><div role="presentation"><style data-emotion="css b7sh1q">.css-b7sh1q,.css-b7sh1q:hover,.css-b7sh1q:active,.css-b7sh1q:focus,.css-b7sh1q:visited,.css-b7sh1q:disabled,.css-b7sh1q[disabled]{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;border-radius:100%;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:inherit;font-style:normal;font-family:inherit;font-weight:500;max-width:100%;position:relative;text-align:center;-webkit-text-decoration:none;text-decoration:none;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);white-space:nowrap;background:var(--ds-background-brand-bold, #0052CC);color:var(--ds-text-subtle, #344563);cursor:pointer;height:auto;line-height:2.2857142857142856em;padding:4px;vertical-align:middle;width:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;outline:none;margin:0 2px;background-color:transparent;}.css-b7sh1q::-moz-focus-inner,.css-b7sh1q:hover::-moz-focus-inner,.css-b7sh1q:active::-moz-focus-inner,.css-b7sh1q:focus::-moz-focus-inner,.css-b7sh1q:visited::-moz-focus-inner,.css-b7sh1q:disabled::-moz-focus-inner,.css-b7sh1q[disabled]::-moz-focus-inner{border:0;margin:0;padding:0;}.css-b7sh1q:hover,.css-b7sh1q:hover:hover,.css-b7sh1q:active:hover,.css-b7sh1q:focus:hover,.css-b7sh1q:visited:hover,.css-b7sh1q:disabled:hover,.css-b7sh1q[disabled]:hover{color:var(--ds-text-subtle, #0052CC);background-color:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));}.css-b7sh1q:focus,.css-b7sh1q:hover:focus,.css-b7sh1q:active:focus,.css-b7sh1q:focus:focus,.css-b7sh1q:visited:focus,.css-b7sh1q:disabled:focus,.css-b7sh1q[disabled]:focus{color:var(--ds-text-subtle, #344563);background-color:var(--ds-background-selected-hovered, rgba(222, 235, 255, 0.5));box-shadow:0 0 0 2px var(--ds-border-focused, #2684FF);}.css-b7sh1q >span,.css-b7sh1q:hover >span,.css-b7sh1q:active >span,.css-b7sh1q:focus >span,.css-b7sh1q:visited >span,.css-b7sh1q:disabled >span,.css-b7sh1q[disabled] >span{margin:0;}</style><button class="css-b7sh1q" data-testid="app-switcher" type="button" tabindex="0"><style data-emotion="css 16j5qb5">.css-16j5qb5{opacity:1;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:0 2px;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;font-size:0;line-height:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}</style><span class="css-16j5qb5"><style data-emotion="css snhnyn">.css-snhnyn{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;}.css-snhnyn >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-snhnyn >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-snhnyn >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}</style><span role="img" aria-label="Documentation" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-snhnyn"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path fill="currentColor" fill-rule="evenodd" d="M4 5.01C4 4.451 4.443 4 5.01 4h1.98C7.549 4 8 4.443 8 5.01v1.98C8 7.549 7.557 8 6.99 8H5.01C4.451 8 4 7.557 4 6.99V5.01zm0 6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98C8 13.549 7.557 14 6.99 14H5.01C4.451 14 4 13.557 4 12.99v-1.98zm6-6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98C14 7.549 13.557 8 12.99 8h-1.98C10.451 8 10 7.557 10 6.99V5.01zm0 6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98c0 .558-.443 1.01-1.01 1.01h-1.98c-.558 0-1.01-.443-1.01-1.01v-1.98zm6-6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98C20 7.549 19.557 8 18.99 8h-1.98C16.451 8 16 7.557 16 6.99V5.01zm0 6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98c0 .558-.443 1.01-1.01 1.01h-1.98c-.558 0-1.01-.443-1.01-1.01v-1.98zm-12 6c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98C8 19.549 7.557 20 6.99 20H5.01C4.451 20 4 19.557 4 18.99v-1.98zm6 0c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98c0 .558-.443 1.01-1.01 1.01h-1.98c-.558 0-1.01-.443-1.01-1.01v-1.98zm6 0c0-.558.443-1.01 1.01-1.01h1.98c.558 0 1.01.443 1.01 1.01v1.98c0 .558-.443 1.01-1.01 1.01h-1.98c-.558 0-1.01-.443-1.01-1.01v-1.98z"/></svg></span></span></button></div><style data-emotion-css="1qtw0hy">.css-1qtw0hy{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:4px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:none;border:0;border-radius:3px;color:inherit;cursor:pointer;}.css-1qtw0hy::-moz-focus-inner{border:0;}.css-1qtw0hy:first-of-type{margin-left:0;}.css-1qtw0hy:hover{background-color:var(--product-home-bg-color-hover);box-shadow:var(--product-home-box-shadow-hover);color:var(--product-home-color-hover);}.css-1qtw0hy:active{background-color:var(--product-home-bg-color-active);box-shadow:var(--product-home-box-shadow-active);color:var(--product-home-color-active);}.css-1qtw0hy:focus{background-color:var(--product-home-bg-color-focus);box-shadow:var(--product-home-box-shadow-focus);color:var(--product-home-color-focus);outline:0;}div.css-1qtw0hy{pointer-events:none;}@media (max-width:1279.9px){.css-1qtw0hy{margin:0 8px;}}@media (min-width:1280px){.css-1qtw0hy{margin:0 16px;}}</style><a style="--product-home-color-active:var(--ds-text-subtle, #0052CC);--product-home-bg-color-active:var(--ds-background-neutral-pressed, rgba(222, 235, 255, 0.7));--product-home-box-shadow-active:;--product-home-color-focus:var(--ds-text-subtle, #344563);--product-home-bg-color-focus:;--product-home-box-shadow-focus:0 0 0 2px var(--ds-border-focused, #2684FF);--product-home-color-hover:var(--ds-text-subtle, #0052CC);--product-home-bg-color-hover:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));--product-home-box-shadow-hover:;--logo-max-width:260px" href="/" data-testid="navigation-container" class="css-1qtw0hy"><style data-emotion-css="3fth2k">.css-3fth2k{max-height:28px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:var(--logo-max-width);}.css-3fth2k > *{max-width:var(--logo-max-width);max-height:24px;}.css-3fth2k > span > svg{width:100%;}@media (max-width:1279.9px){.css-3fth2k{display:none;}}</style><div data-testid="navigation-logo" class="css-3fth2k"><svg width="261" height="25" viewBox="0 0 261 25" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="260.25" height="24" transform="translate(0 1)" fill="white" fill-opacity="0.01"></rect><path d="M5.3024 9.13208C5.03183 8.83445 4.62597 8.86149 4.43657 9.21323L0.0533155 18.0068C-0.109027 18.3586 0.134487 18.7644 0.513287 18.7644H6.6282C6.8176 18.7644 7.007 18.6562 7.08818 18.4668C8.44103 15.7611 7.62932 11.6213 5.3024 9.13208Z" fill="url(#paint0_linear)"></path><path d="M8.52267 1.15012C6.06047 5.04635 6.22281 9.34842 7.84624 12.5953C9.46967 15.8421 10.7143 18.3044 10.7955 18.4938C10.8766 18.6832 11.066 18.7914 11.2554 18.7914H17.3704C17.7492 18.7914 18.0197 18.3855 17.8303 18.0338C17.8303 18.0338 9.60495 1.58303 9.3885 1.17718C9.25321 0.771318 8.76618 0.771325 8.52267 1.15012Z" fill="#2684FF"></path><path d="M91.6158 14.4351C91.6158 11.8647 90.2359 10.6471 86.3937 9.80834C84.2562 9.34837 83.7422 8.86134 83.7422 8.18492C83.7422 7.34614 84.4998 6.96734 85.9067 6.96734C87.6113 6.96734 89.2889 7.48142 90.8852 8.21197V4.82982C89.7759 4.26162 88.0442 3.82869 86.015 3.82869C82.1999 3.82869 80.2247 5.47919 80.2247 8.21197C80.2247 10.3765 81.2258 12.1082 85.1762 12.8658C87.5301 13.3528 88.0172 13.7316 88.0172 14.5163C88.0172 15.2739 87.5301 15.7609 85.8526 15.7609C83.9315 15.7609 81.6317 15.1115 80.1436 14.2186V17.7631C81.3341 18.3584 82.9034 19.0078 85.8256 19.0078C89.9924 19.0078 91.6158 17.1679 91.6158 14.4351Z" fill="#0052CC"></path><path d="M133.256 4.04523V18.7643H136.395V7.53561L137.721 10.5119L142.158 18.7643H146.108V4.04523H142.97V13.5423L141.779 10.7825L138.208 4.04523H133.256Z" fill="#0052CC"></path><path d="M113.288 4.04523H109.851V18.7643H113.288V4.04523Z" fill="#0052CC"></path><path d="M105.901 14.4351C105.901 11.8647 104.522 10.6471 100.679 9.80834C98.5419 9.34837 98.0278 8.86134 98.0278 8.18492C98.0278 7.34614 98.7854 6.96734 100.192 6.96734C101.897 6.96734 103.575 7.48142 105.171 8.21197V4.82982C104.062 4.26162 102.33 3.82869 100.301 3.82869C96.4855 3.82869 94.5104 5.47919 94.5104 8.21197C94.5104 10.3765 95.5115 12.1082 99.4618 12.8658C101.816 13.3528 102.303 13.7316 102.303 14.5163C102.303 15.2739 101.816 15.7609 100.138 15.7609C98.2172 15.7609 95.9173 15.1115 94.4292 14.2186V17.7631C95.6197 18.3584 97.189 19.0078 100.111 19.0078C104.278 19.0078 105.901 17.1679 105.901 14.4351Z" fill="#0052CC"></path><path d="M53.5997 4.04523V18.7643H60.6616L61.771 15.5986H57.063V4.04523H53.5997Z" fill="#0052CC"></path><path d="M39.6926 4.0453V7.23806H43.5077V18.7644H46.9439V7.23806H51.0296V4.0453H39.6926Z" fill="#0052CC"></path><path d="M34.6874 4.04523H30.1688L25.028 18.7643H28.9512L29.6818 16.275C30.5476 16.5186 31.4676 16.6809 32.4416 16.6809C33.3886 16.6809 34.3086 16.5456 35.2014 16.275L35.932 18.7643H39.8553L34.6874 4.04523ZM32.4146 13.6505C31.7652 13.6505 31.1158 13.5423 30.5206 13.3799L32.4146 6.94033L34.3086 13.3799C33.7133 13.5423 33.0639 13.6505 32.4146 13.6505Z" fill="#0052CC"></path><path d="M72.8113 4.04521H68.2927L63.1519 18.7643H67.0751L67.8057 16.275C68.6715 16.5185 69.5915 16.6809 70.5655 16.6809C71.5125 16.6809 72.4325 16.5456 73.3253 16.275L74.0559 18.7643H77.9792L72.8113 4.04521ZM70.5655 13.6505C69.9161 13.6505 69.2668 13.5423 68.6715 13.3799L70.5655 6.94031L72.4595 13.3799C71.8372 13.5423 71.2149 13.6505 70.5655 13.6505Z" fill="#0052CC"></path><path d="M125.653 4.04521H121.135L115.994 18.7643H119.917L120.648 16.275C121.514 16.5185 122.433 16.6809 123.408 16.6809C124.355 16.6809 125.274 16.5456 126.167 16.275L126.898 18.7643H130.821L125.653 4.04521ZM123.38 13.6505C122.731 13.6505 122.082 13.5423 121.486 13.3799L123.38 6.94031L125.274 13.3799C124.679 13.5423 124.057 13.6505 123.38 13.6505Z" fill="#0052CC"></path><path d="M155.334 2.93684H161.151C166.292 2.93684 168.754 6.12959 168.754 10.8917C168.754 15.6808 166.238 18.7653 161.151 18.7653H155.334V2.93684ZM157.498 5.02023V16.7089H161.178C164.804 16.7089 166.59 14.8149 166.59 10.9728C166.59 7.13069 164.885 5.02023 161.043 5.02023H157.498Z" fill="#253858"></path><path d="M177.062 19.0079C172.57 19.0079 170.595 16.4104 170.595 12.7307C170.595 9.105 172.624 6.48046 176.277 6.48046C179.984 6.48046 181.472 9.05088 181.472 12.7307V13.6777H172.678C172.976 15.734 174.302 17.0598 177.143 17.0598C178.55 17.0598 179.713 16.7892 180.796 16.4104V18.3044C179.794 18.8185 178.279 19.0079 177.062 19.0079ZM172.651 11.8919H179.361C179.253 9.64615 178.225 8.37446 176.169 8.37446C173.977 8.37446 172.868 9.78143 172.651 11.8919Z" fill="#253858"></path><path d="M187.235 18.7644L182.554 6.72401H184.719L188.615 17.0057L192.484 6.72401H194.648L189.968 18.7644H187.235Z" fill="#253858"></path><path d="M201.737 19.0079C197.245 19.0079 195.27 16.4104 195.27 12.7307C195.27 9.105 197.299 6.48046 200.952 6.48046C204.659 6.48046 206.147 9.05088 206.147 12.7307V13.6777H197.354C197.651 15.734 198.977 17.0598 201.818 17.0598C203.225 17.0598 204.388 16.7892 205.471 16.4104V18.3044C204.497 18.8185 202.981 19.0079 201.737 19.0079ZM197.326 11.8919H204.037C203.928 9.64615 202.9 8.37446 200.844 8.37446C198.652 8.37446 197.543 9.78143 197.326 11.8919Z" fill="#253858"></path><path d="M211.829 18.8456C209.854 18.8456 208.61 17.8986 208.61 15.6799V1.69136H210.693V15.4364C210.693 16.5187 211.424 16.8975 212.316 16.8975C212.533 16.8975 212.668 16.8975 212.912 16.8704V18.7374C212.722 18.7915 212.371 18.8456 211.829 18.8456Z" fill="#253858"></path><path d="M214.049 12.7307C214.049 9.105 216.159 6.48046 219.785 6.48046C223.384 6.48046 225.467 9.105 225.467 12.7307C225.467 16.3563 223.384 19.0079 219.785 19.0079C216.159 19.0079 214.049 16.3293 214.049 12.7307ZM216.078 12.7307C216.078 15.0305 217.215 17.0869 219.785 17.0869C222.328 17.0869 223.438 15.0035 223.438 12.7307C223.438 10.4308 222.328 8.42856 219.785 8.42856C217.215 8.40151 216.078 10.4308 216.078 12.7307Z" fill="#253858"></path><path d="M229.931 16.6539V23.4724H227.848V6.72398H229.931V8.88855C230.689 7.29218 232.15 6.48046 233.99 6.48046C237.183 6.48046 238.806 9.21323 238.806 12.7307C238.806 16.1399 237.129 18.9809 233.746 18.9809C232.015 19.0079 230.662 18.2233 229.931 16.6539ZM233.449 8.40151C231.582 8.40151 229.931 9.59205 229.931 12.2436V13.2177C229.931 15.8964 231.447 17.0598 233.205 17.0598C235.532 17.0598 236.75 15.5175 236.75 12.7307C236.75 9.8626 235.613 8.40151 233.449 8.40151Z" fill="#253858"></path><path d="M247.004 19.0079C242.512 19.0079 240.537 16.4104 240.537 12.7307C240.537 9.105 242.566 6.48046 246.219 6.48046C249.926 6.48046 251.414 9.05088 251.414 12.7307V13.6777H242.62C242.918 15.734 244.244 17.0598 247.085 17.0598C248.492 17.0598 249.655 16.7892 250.737 16.4104V18.3044C249.736 18.8185 248.221 19.0079 247.004 19.0079ZM242.593 11.8919H249.303C249.195 9.64615 248.167 8.37446 246.111 8.37446C243.919 8.37446 242.81 9.78143 242.593 11.8919Z" fill="#253858"></path><path d="M255.878 18.7645H253.848V6.7241H255.878V8.83454C256.581 7.40051 257.772 6.39939 260.153 6.53468V8.56396C257.501 8.29339 255.878 9.10511 255.878 11.6485V18.7645Z" fill="#253858"></path><defs><linearGradient id="paint0_linear" x1="7.72023" y1="10.4927" x2="3.08501" y2="18.5211" gradientUnits="userSpaceOnUse"><stop stop-color="#0052CC"></stop><stop offset="0.9228" stop-color="#2684FF"></stop></linearGradient></defs></svg></div><style data-emotion-css="15lsza2">.css-15lsza2{max-height:28px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}.css-15lsza2 > *{max-height:24px;}@media (min-width:1280px){.css-15lsza2{display:none;}}</style><div data-testid="navigation-icon" class="css-15lsza2"><style data-emotion="css 1hj8rln">.css-1hj8rln{display:inline-block;position:relative;color:var(--logo-color);fill:var(--logo-fill);line-height:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:normal;height:32px;}.css-1hj8rln >svg{height:100%;fill:inherit;}.css-1hj8rln stop{stop-color:currentColor;}</style><span style="--logo-color:#2684FF;--logo-fill:currentColor" aria-label="Atlassian" role="img" class="css-1hj8rln"><svg fill="none" height="32" viewBox="0 0 32 32" focusable="false" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> <path fill="#2684FF" d="M27.545 24.378 16.96 3.208c-.208-.458-.417-.541-.667-.541-.208 0-.458.083-.708.5-1.5 2.375-2.167 5.125-2.167 8 0 4.001 2.042 7.752 5.042 13.795.334.666.584.791 1.167.791h7.335c.541 0 .833-.208.833-.625 0-.208-.042-.333-.25-.75M12.168 14.377c-.834-1.25-1.084-1.334-1.292-1.334s-.333.083-.708.834L4.875 24.46c-.167.334-.208.459-.208.625 0 .334.291.667.916.667h7.46c.5 0 .875-.416 1.083-1.208.25-1 .334-1.876.334-2.917 0-2.917-1.292-5.751-2.292-7.251"/> </svg></span></div></a><style data-emotion-css="sufdiy">.css-sufdiy{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:4px;margin-left:4px;padding-right:16px;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}</style><div style="border-right:1px solid var(--ds-border, rgba(107, 119, 140, 0.3))" data-testid="navigation-site-title" class="css-sufdiy">Forge</div><style data-emotion-css="uiquy5">.css-uiquy5{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;position:relative;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-flex-basis:0;-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.css-uiquy5 > *{margin:0 4px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><div class="css-uiquy5"><style data-emotion-css="le7mka">.css-le7mka{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;position:relative;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}</style><div style="--button-selected-color:var(--ds-text-selected, #0052CC);--button-selected-border-color:var(--ds-border-selected, #0052CC)" class="css-le7mka"><style data-emotion="css 4mgr5f">.css-4mgr5f,.css-4mgr5f:hover,.css-4mgr5f:active,.css-4mgr5f:focus,.css-4mgr5f:visited,.css-4mgr5f:disabled,.css-4mgr5f[disabled]{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;border-radius:3px;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-family:inherit;font-weight:500;max-width:100%;position:relative;text-align:center;-webkit-text-decoration:none;text-decoration:none;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);white-space:nowrap;background:var(--ds-background-brand-bold, #0052CC);color:var(--ds-text-subtle, #344563);cursor:pointer;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 4px;vertical-align:middle;width:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;outline:none;background-color:transparent;margin-left:0;margin-right:0;}.css-4mgr5f::-moz-focus-inner,.css-4mgr5f:hover::-moz-focus-inner,.css-4mgr5f:active::-moz-focus-inner,.css-4mgr5f:focus::-moz-focus-inner,.css-4mgr5f:visited::-moz-focus-inner,.css-4mgr5f:disabled::-moz-focus-inner,.css-4mgr5f[disabled]::-moz-focus-inner{border:0;margin:0;padding:0;}.css-4mgr5f:hover,.css-4mgr5f:hover:hover,.css-4mgr5f:active:hover,.css-4mgr5f:focus:hover,.css-4mgr5f:visited:hover,.css-4mgr5f:disabled:hover,.css-4mgr5f[disabled]:hover{color:var(--ds-text-subtle, #0052CC);background-color:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));}.css-4mgr5f:focus,.css-4mgr5f:hover:focus,.css-4mgr5f:active:focus,.css-4mgr5f:focus:focus,.css-4mgr5f:visited:focus,.css-4mgr5f:disabled:focus,.css-4mgr5f[disabled]:focus{color:var(--ds-text-subtle, #344563);box-shadow:0 0 0 2px var(--ds-border-focused, #2684FF);}</style><a class="css-4mgr5f" href="/platform/forge/" data-testid="Guides" tabindex="0"><style data-emotion="css 178ag6o">.css-178ag6o{opacity:1;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;margin:0 2px;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><span class="css-178ag6o">Guides</span></a></div><div style="--button-selected-color:var(--ds-text-selected, #0052CC);--button-selected-border-color:var(--ds-border-selected, #0052CC)" class="css-le7mka"><style data-emotion="css 4mgr5f">.css-4mgr5f,.css-4mgr5f:hover,.css-4mgr5f:active,.css-4mgr5f:focus,.css-4mgr5f:visited,.css-4mgr5f:disabled,.css-4mgr5f[disabled]{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;border-radius:3px;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-family:inherit;font-weight:500;max-width:100%;position:relative;text-align:center;-webkit-text-decoration:none;text-decoration:none;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);white-space:nowrap;background:var(--ds-background-brand-bold, #0052CC);color:var(--ds-text-subtle, #344563);cursor:pointer;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 4px;vertical-align:middle;width:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;outline:none;background-color:transparent;margin-left:0;margin-right:0;}.css-4mgr5f::-moz-focus-inner,.css-4mgr5f:hover::-moz-focus-inner,.css-4mgr5f:active::-moz-focus-inner,.css-4mgr5f:focus::-moz-focus-inner,.css-4mgr5f:visited::-moz-focus-inner,.css-4mgr5f:disabled::-moz-focus-inner,.css-4mgr5f[disabled]::-moz-focus-inner{border:0;margin:0;padding:0;}.css-4mgr5f:hover,.css-4mgr5f:hover:hover,.css-4mgr5f:active:hover,.css-4mgr5f:focus:hover,.css-4mgr5f:visited:hover,.css-4mgr5f:disabled:hover,.css-4mgr5f[disabled]:hover{color:var(--ds-text-subtle, #0052CC);background-color:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));}.css-4mgr5f:focus,.css-4mgr5f:hover:focus,.css-4mgr5f:active:focus,.css-4mgr5f:focus:focus,.css-4mgr5f:visited:focus,.css-4mgr5f:disabled:focus,.css-4mgr5f[disabled]:focus{color:var(--ds-text-subtle, #344563);box-shadow:0 0 0 2px var(--ds-border-focused, #2684FF);}</style><a class="css-4mgr5f" href="/platform/forge/manifest-reference/" data-testid="Reference" tabindex="0"><style data-emotion="css 178ag6o">.css-178ag6o{opacity:1;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;margin:0 2px;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><span class="css-178ag6o">Reference</span></a></div><div style="--button-selected-color:var(--ds-text-selected, #0052CC);--button-selected-border-color:var(--ds-border-selected, #0052CC)" class="css-le7mka"><style data-emotion="css 4mgr5f">.css-4mgr5f,.css-4mgr5f:hover,.css-4mgr5f:active,.css-4mgr5f:focus,.css-4mgr5f:visited,.css-4mgr5f:disabled,.css-4mgr5f[disabled]{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;border-radius:3px;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-family:inherit;font-weight:500;max-width:100%;position:relative;text-align:center;-webkit-text-decoration:none;text-decoration:none;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);white-space:nowrap;background:var(--ds-background-brand-bold, #0052CC);color:var(--ds-text-subtle, #344563);cursor:pointer;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 4px;vertical-align:middle;width:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;outline:none;background-color:transparent;margin-left:0;margin-right:0;}.css-4mgr5f::-moz-focus-inner,.css-4mgr5f:hover::-moz-focus-inner,.css-4mgr5f:active::-moz-focus-inner,.css-4mgr5f:focus::-moz-focus-inner,.css-4mgr5f:visited::-moz-focus-inner,.css-4mgr5f:disabled::-moz-focus-inner,.css-4mgr5f[disabled]::-moz-focus-inner{border:0;margin:0;padding:0;}.css-4mgr5f:hover,.css-4mgr5f:hover:hover,.css-4mgr5f:active:hover,.css-4mgr5f:focus:hover,.css-4mgr5f:visited:hover,.css-4mgr5f:disabled:hover,.css-4mgr5f[disabled]:hover{color:var(--ds-text-subtle, #0052CC);background-color:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));}.css-4mgr5f:focus,.css-4mgr5f:hover:focus,.css-4mgr5f:active:focus,.css-4mgr5f:focus:focus,.css-4mgr5f:visited:focus,.css-4mgr5f:disabled:focus,.css-4mgr5f[disabled]:focus{color:var(--ds-text-subtle, #344563);box-shadow:0 0 0 2px var(--ds-border-focused, #2684FF);}</style><a class="css-4mgr5f" href="/platform/forge/get-help/" data-testid="Get help" tabindex="0"><style data-emotion="css 178ag6o">.css-178ag6o{opacity:1;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;margin:0 2px;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><span class="css-178ag6o">Get help</span></a></div><div style="--button-selected-color:var(--ds-text-selected, #0052CC);--button-selected-border-color:var(--ds-border-selected, #0052CC)" class="css-le7mka"><style data-emotion="css 4mgr5f">.css-4mgr5f,.css-4mgr5f:hover,.css-4mgr5f:active,.css-4mgr5f:focus,.css-4mgr5f:visited,.css-4mgr5f:disabled,.css-4mgr5f[disabled]{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;border-radius:3px;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-family:inherit;font-weight:500;max-width:100%;position:relative;text-align:center;-webkit-text-decoration:none;text-decoration:none;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38);white-space:nowrap;background:var(--ds-background-brand-bold, #0052CC);color:var(--ds-text-subtle, #344563);cursor:pointer;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 4px;vertical-align:middle;width:auto;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;outline:none;background-color:transparent;margin-left:0;margin-right:0;}.css-4mgr5f::-moz-focus-inner,.css-4mgr5f:hover::-moz-focus-inner,.css-4mgr5f:active::-moz-focus-inner,.css-4mgr5f:focus::-moz-focus-inner,.css-4mgr5f:visited::-moz-focus-inner,.css-4mgr5f:disabled::-moz-focus-inner,.css-4mgr5f[disabled]::-moz-focus-inner{border:0;margin:0;padding:0;}.css-4mgr5f:hover,.css-4mgr5f:hover:hover,.css-4mgr5f:active:hover,.css-4mgr5f:focus:hover,.css-4mgr5f:visited:hover,.css-4mgr5f:disabled:hover,.css-4mgr5f[disabled]:hover{color:var(--ds-text-subtle, #0052CC);background-color:var(--ds-background-neutral-hovered, rgba(222, 235, 255, 0.9));}.css-4mgr5f:focus,.css-4mgr5f:hover:focus,.css-4mgr5f:active:focus,.css-4mgr5f:focus:focus,.css-4mgr5f:visited:focus,.css-4mgr5f:disabled:focus,.css-4mgr5f[disabled]:focus{color:var(--ds-text-subtle, #344563);box-shadow:0 0 0 2px var(--ds-border-focused, #2684FF);}</style><a class="css-4mgr5f" href="/platform/forge/changelog/" data-testid="Changelog" tabindex="0"><style data-emotion="css 178ag6o">.css-178ag6o{opacity:1;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;margin:0 2px;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><span class="css-178ag6o">Changelog</span></a></div><style data-emotion-css="1ozpmrm">.css-1ozpmrm{width:100%;min-width:1px;margin:0px;position:relative;-webkit-flex-shrink:1;-ms-flex-negative:1;flex-shrink:1;}</style><div class="css-1ozpmrm"><div style="display:block;width:100%;position:absolute"></div></div></div></nav><style data-emotion-css="d4blq8">.css-d4blq8{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.css-d4blq8 > *{margin-right:4px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><div class="css-d4blq8"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="16" height="16" viewBox="0 0 24 24" role="presentation"><path d="M16.436 15.085l3.94 4.01a1 1 0 01-1.425 1.402l-3.938-4.006a7.5 7.5 0 111.423-1.406zM10.5 16a5.5 5.5 0 100-11 5.5 5.5 0 000 11z" fill="currentColor" fill-rule="evenodd"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button><div class="sc-eNPDpu iARtDw"></div><style data-emotion-css="1pys61m">a.css-1pys61m{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-weight:500;max-width:100%;outline:none !important;text-align:center;-webkit-text-decoration:none;text-decoration:none;white-space:nowrap;background:none;border-radius:3px;box-shadow:0 0 0 2px inherit;color:#42526E !important;cursor:default;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 8px;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);-webkit-transition-duration:0.1s,0.15s;transition-duration:0.1s,0.15s;vertical-align:middle;width:auto;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;}a.css-1pys61m::-moz-focus-inner{border:0;margin:0;padding:0;}a.css-1pys61m:hover{-webkit-text-decoration:inherit;text-decoration:inherit;}</style><a href="/support" type="button" class="css-1pys61m"><style data-emotion-css="j8fq0c">.css-j8fq0c{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%;position:relative;}</style><span class="css-j8fq0c"><style data-emotion-css="t5emrf">.css-t5emrf{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin:0 4px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;opacity:1;}</style><span class="css-t5emrf">Support</span></span></a><style data-emotion-css="9b4v41">a.css-9b4v41{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-weight:500;max-width:100%;outline:none !important;text-align:center;-webkit-text-decoration:none;text-decoration:none;white-space:nowrap;background:rgba(9,30,66,0.04);border-radius:3px;box-shadow:0 0 0 2px inherit;color:#42526E !important;cursor:default;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 8px;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);-webkit-transition-duration:0.1s,0.15s;transition-duration:0.1s,0.15s;vertical-align:middle;width:auto;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;}a.css-9b4v41::-moz-focus-inner{border:0;margin:0;padding:0;}a.css-9b4v41:hover{-webkit-text-decoration:inherit;text-decoration:inherit;}</style><a href="/account/login?returnTo=%2Fplatform%2Fforge%2F" type="button" class="css-9b4v41"><span class="css-j8fq0c"><span class="css-t5emrf">Log in</span></span></a></div></header></div></div><div class="sc-gVZiCL BlNLE sc-hBcjXN iLnIWi"><div class="sc-jBoNkH eGFUop"><nav class="sc-fPbjcq fdZVrh"><ul class="sc-jgVwMx ixXsyz sc-dBfaGr hMVyQH"><li class="sc-eQGPmX ebjqXf"><div class="sc-hMjcWo jOJzhX"><style data-emotion-css="1pys61m">a.css-1pys61m{-webkit-align-items:baseline;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;border-width:0;box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:inherit;font-style:normal;font-weight:500;max-width:100%;outline:none !important;text-align:center;-webkit-text-decoration:none;text-decoration:none;white-space:nowrap;background:none;border-radius:3px;box-shadow:0 0 0 2px inherit;color:#42526E !important;cursor:default;height:2.2857142857142856em;line-height:2.2857142857142856em;padding:0 8px;-webkit-transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);transition:background 0.1s ease-out,box-shadow 0.15s cubic-bezier(0.47,0.03,0.49,1.38);-webkit-transition-duration:0.1s,0.15s;transition-duration:0.1s,0.15s;vertical-align:middle;width:auto;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;}a.css-1pys61m::-moz-focus-inner{border:0;margin:0;padding:0;}a.css-1pys61m:hover{-webkit-text-decoration:inherit;text-decoration:inherit;}</style><a href="/platform/forge/" type="button" class="css-1pys61m"><style data-emotion-css="j8fq0c">.css-j8fq0c{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%;position:relative;}</style><span class="css-j8fq0c"><style data-emotion-css="t5emrf">.css-t5emrf{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;margin:0 4px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;-webkit-transition:opacity 0.3s;transition:opacity 0.3s;opacity:1;}</style><span class="css-t5emrf"><span class="sc-dAOnuy gupbxx">About Forge</span></span></span></a></div></li></ul><ul class="sc-dBfaGr hMVyQH"><li class="sc-jGFFOr iJfdrZ"><div class="sc-hZeNU dZmoXu">Get started</div><style data-emotion="css 1dlapeh">.css-1dlapeh{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:static;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;}</style><div class="css-1dlapeh"><ul class="sc-cSYcjD EsMfL"><style data-emotion="css 8zknns">.css-8zknns{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;}</style><div class="css-8zknns"><style data-emotion="css lzie5a 1cy6ofv 5mekwu">.css-lzie5a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-lzie5a::-moz-focus-inner{border:0;}.css-lzie5a:hover{-webkit-text-decoration:none;text-decoration:none;}.css-lzie5a:visited{color:currentColor;}.css-lzie5a:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-lzie5a:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-1cy6ofv{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-1cy6ofv::-moz-focus-inner{border:0;}.css-1cy6ofv:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1cy6ofv:visited{color:currentColor;}.css-1cy6ofv:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-1cy6ofv:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-5mekwu{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><style data-emotion="css 38t7l3 vbpl3">.css-38t7l3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-38t7l3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-vbpl3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-vbpl3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3::-moz-focus-inner{border:0;}.css-vbpl3:hover{-webkit-text-decoration:none;text-decoration:none;}.css-vbpl3:visited{color:currentColor;}.css-vbpl3:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-vbpl3:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}</style><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><style data-emotion="css fdr7fn">.css-fdr7fn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:var(--ds-scale-150, 12px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><span data-item-elem-before="true" class="css-fdr7fn"><style data-emotion="css 3zleef">.css-3zleef{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;text-align:center;-webkit-transform:none;-moz-transform:none;-ms-transform:none;transform:none;}</style><div class="css-3zleef"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><style data-emotion="css 1gly9cj">.css-1gly9cj{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;line-height:1.22;outline:none;overflow:hidden;text-align:left;}</style><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css 1mgvn46">.css-1mgvn46{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;font-size:14px;line-height:20px;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center;white-space:normal;color:var(--ds-text-subtle, #42526E);}</style><div class="css-1mgvn46">Introduction to Forge</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/introduction/the-forge-platform/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css jv18ke">.css-jv18ke{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;white-space:normal;overflow:visible;color:var(--ds-text-subtle, #42526E);word-wrap:break-word;text-align:left;box-sizing:border-box;overflow-wrap:break-word;font-size:14px;font-weight:400;line-height:20px;}</style><div class="css-jv18ke">The Forge platform</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/introduction/why-build-with-forge/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Why build with Forge</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Migrate your Connect app</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="https://developer.atlassian.com/platform/adopting-forge-from-connect/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Adopting Forge from Connect</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><style data-emotion="css 1fpc7od">.css-1fpc7od{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;text-align:center;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);}</style><div class="css-1fpc7od"><span role="img" aria-label="close" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Learn</div></span></span></button></div><ul class="sc-cSYcjD EsMfL"><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Example apps</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-bitbucket/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Bitbucket</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-compass/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Compass</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-confluence/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Confluence</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-jira/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Jira</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-jsm/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Jira Service Management</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/example-apps-rovo/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Rovo</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-1fpc7od"><span role="img" aria-label="close" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Guided tutorials</div></span></span></button></div><ul class="sc-cSYcjD EsMfL"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/tutorials-and-guides/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/forge-compass-cloudwatch/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge, Compass, and AWS CloudWatch</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/add-scheduled-trigger/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Schedule web triggers</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/debug-functions-using-intellij/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Debug functions using IntelliJ</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/debug-functions-using-vscode/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Debug functions using VS Code</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/profiling-node-js-app-code-tunnel/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Profile app performance with tunnel debugger</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/implement-a-dynamic-profile-retriever-with-external-authentication/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Implement a dynamic profile retriever</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="https://developer.atlassian.com/platform/adopting-forge-from-connect/migrate-macro" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Migrate an app from Connect to Forge</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/ui-kit/migration-example/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Migrate an app from UI Kit 1 to UI Kit</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/set-up-cicd/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Set up continuous delivery</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/storage-api-limit-handling/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Queue app interactions with Storage API</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/use-a-long-running-function" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use a long-running function</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/custom-entities-store-structured-data/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use custom entities to store structured data</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/use-an-external-oauth-2.0-api-with-fetch/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use an external OAuth 2.0 API with fetch</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/add-routing-to-a-full-page-app/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Add routing to a full-page app in Jira</div></span></span></a><style data-emotion="css 15wxdop 1r33r0e 5mekwu">.css-15wxdop{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:var(--ds-background-selected, #F4F5F7);color:var(--ds-text-selected, currentColor);cursor:pointer;}.css-15wxdop::-moz-focus-inner{border:0;}.css-15wxdop:hover{-webkit-text-decoration:none;text-decoration:none;}.css-15wxdop:visited{color:var(--ds-text-selected, currentColor);}.css-15wxdop:hover{background-color:var(--ds-background-selected-hovered, #F4F5F7);color:var(--ds-text-selected, currentColor);}.css-15wxdop:active{background-color:var(--ds-background-selected-pressed, #EBECF0);color:var(--ds-text-selected, currentColor);}.css-1r33r0e{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:var(--ds-background-selected, #F4F5F7);color:var(--ds-text-selected, currentColor);cursor:pointer;}.css-1r33r0e::-moz-focus-inner{border:0;}.css-1r33r0e:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1r33r0e:visited{color:var(--ds-text-selected, currentColor);}.css-1r33r0e:hover{background-color:var(--ds-background-selected-hovered, #F4F5F7);color:var(--ds-text-selected, currentColor);}.css-1r33r0e:active{background-color:var(--ds-background-selected-pressed, #EBECF0);color:var(--ds-text-selected, currentColor);}</style><style data-emotion="css 38t7l3 h3wgus">.css-h3wgus{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:var(--ds-background-selected, #F4F5F7);color:var(--ds-text-selected, currentColor);cursor:pointer;}.css-h3wgus:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-h3wgus:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-h3wgus:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-h3wgus:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-h3wgus::-moz-focus-inner{border:0;}.css-h3wgus:hover{-webkit-text-decoration:none;text-decoration:none;}.css-h3wgus:visited{color:var(--ds-text-selected, currentColor);}.css-h3wgus:hover{background-color:var(--ds-background-selected-hovered, #F4F5F7);color:var(--ds-text-selected, currentColor);}.css-h3wgus:active{background-color:var(--ds-background-selected-pressed, #EBECF0);color:var(--ds-text-selected, currentColor);}</style><a class="sc-dOkuiw kyARPC css-h3wgus" leftPaddingSize="2" href="/platform/forge/create-confluence-macro-with-storage-api" draggable="false" aria-current="page" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css 5f0sa">.css-5f0sa{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;white-space:normal;overflow:visible;color:var(--ds-text-selected, #0052CC);word-wrap:break-word;text-align:left;box-sizing:border-box;overflow-wrap:break-word;font-size:14px;font-weight:400;line-height:20px;}</style><div class="css-5f0sa">Use the storage API in Confluence</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/add-custom-configuration-to-a-macro" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Add custom configuration to a macro</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/using-rich-text-bodied-macros" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Using rich body macros</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Rovo</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/extend-atlassian-products-with-a-forge-rovo-agent/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Extend Atlassian products with a Forge Rovo agent</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-hello-world-rovo-agent/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Rovo Agent app</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-q-and-a-rovo-agent-for-confluence" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Q&amp;A Rovo Agent for Confluence</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-jira-issue-analyst-rovo-agent" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Jira issue analyst Rovo Agent</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Jira</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-hello-world-app-in-jira/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a hello world app in Jira</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/automate-jira-using-triggers/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Automate Jira with triggers</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-jira-comments-summarizer-with-openai/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Jira comments summarizer app with OpenAI</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/check-jira-issues-assigned-using-workflow-validator/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use a workflow validator to check issue assignments</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-custom-ui-app-in-jira/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a custom UI app</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Jira Service Management</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-hello-world-app-in-jira-service-management/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a hello world app in Jira Service Management</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/assets-import-app/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Import third party data into Assets</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/queue-events-with-async-events-api-to-import-assets/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use Async Events API to queue jobs to import objects into Assets</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-custom-ui-app-in-jira-service-management/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a custom UI app</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Confluence</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-hello-world-app-in-confluence/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a hello world app in Confluence</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/create-a-question-generator-app-in-multiple-languages-using-i18n/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Create a question generator app in multiple languages using i18n</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/create-a-quiz-app-using-ui-kit/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Create a quiz app using UI Kit</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/add-configuration-to-a-macro-with-ui-kit/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Add configuration to a macro with UI Kit</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/ui-kit/components/frame-tutorial/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Create a logo designer app using the Frame component (Preview)</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/space-news/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use space settings and content byline to implement space news</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/macros-in-the-page/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use content actions to count page macros</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-custom-ui-app-in-confluence/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Custom UI app</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-confluence-keyword-extractor-with-openai/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a Confluence keyword extractor with OpenAI</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/create-confluence-contextmenu-module/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use highlighted text in a Confluence app</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/create-a-giphy-app-using-the-ui-kit/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Create a GIPHY app using UI kit on Confluence</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Bitbucket</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/extend-bitbucket-cloud/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Extend Bitbucket Cloud</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-hello-world-app-in-bitbucket/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a hello world app in Bitbucket</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/automate-bitbucket-using-triggers/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Automate Bitbucket with triggers</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/build-a-pull-request-title-validator-with-custom-merge-checks/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build a pull request title validator with custom merge checks</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/orchestrate-your-builds-using-dynamic-pipelines/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Orchestrate your builds using Dynamic Pipelines</div></span></span></a></ul></ul><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="https://developer.atlassian.com/developer-guide/glossary/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Atlassian developer glossary</div></span></span></a></ul></ul></div></li><li class="sc-jGFFOr iJfdrZ"><div class="sc-hZeNU dZmoXu">Plan &amp; design</div><style data-emotion="css 1dlapeh">.css-1dlapeh{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:static;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;}</style><div class="css-1dlapeh"><ul class="sc-cSYcjD EsMfL"><style data-emotion="css 8zknns">.css-8zknns{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;}</style><div class="css-8zknns"><style data-emotion="css lzie5a 1cy6ofv 5mekwu">.css-lzie5a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-lzie5a::-moz-focus-inner{border:0;}.css-lzie5a:hover{-webkit-text-decoration:none;text-decoration:none;}.css-lzie5a:visited{color:currentColor;}.css-lzie5a:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-lzie5a:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-1cy6ofv{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-1cy6ofv::-moz-focus-inner{border:0;}.css-1cy6ofv:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1cy6ofv:visited{color:currentColor;}.css-1cy6ofv:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-1cy6ofv:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-5mekwu{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><style data-emotion="css 38t7l3 vbpl3">.css-38t7l3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-38t7l3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-vbpl3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-vbpl3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3::-moz-focus-inner{border:0;}.css-vbpl3:hover{-webkit-text-decoration:none;text-decoration:none;}.css-vbpl3:visited{color:currentColor;}.css-vbpl3:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-vbpl3:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}</style><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><style data-emotion="css fdr7fn">.css-fdr7fn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:var(--ds-scale-150, 12px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><span data-item-elem-before="true" class="css-fdr7fn"><style data-emotion="css 3zleef">.css-3zleef{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;text-align:center;-webkit-transform:none;-moz-transform:none;-ms-transform:none;transform:none;}</style><div class="css-3zleef"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><style data-emotion="css 1gly9cj">.css-1gly9cj{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;line-height:1.22;outline:none;overflow:hidden;text-align:left;}</style><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css 1mgvn46">.css-1mgvn46{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;font-size:14px;line-height:20px;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center;white-space:normal;color:var(--ds-text-subtle, #42526E);}</style><div class="css-1mgvn46">App architecture</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/events/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css jv18ke">.css-jv18ke{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;white-space:normal;overflow:visible;color:var(--ds-text-subtle, #42526E);word-wrap:break-word;text-align:left;box-sizing:border-box;overflow-wrap:break-word;font-size:14px;font-weight:400;line-height:20px;}</style><div class="css-jv18ke">Events and triggers</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/storage/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Hosted storage</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/storage-reference/hosted-storage-data-lifecycle/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Hosted storage data lifecycle</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/manifest/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Manifest</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/modules/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Modules</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Platform quotas and limits</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/platform-quotas-and-limits/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">User interface</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/user-interface/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/ui-kit/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Build with UI Kit</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/extend-ui-with-custom-options/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Extend UI with custom options</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/design-tokens-and-theming/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Design tokens and theming</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/internationalization/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Internationalization</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/understanding-ui-modifications/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Understanding the UI modifications module</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/jira-full-page-modules/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Jira full page modules</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Legal &amp; privacy</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/developer-terms/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge terms of use</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/shared-responsibility-model/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Shared responsibility model</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/faq-privacy-security/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge privacy and security FAQ</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/user-privacy-guidelines/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">User privacy guide</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/about-the-forge-data-processing-addendum/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge Data Processing Addendum</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/logging-guidelines/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Logging data</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Best practice</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/security/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">App security</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">App distribution</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/staging-and-production-apps/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Promote an app from staging to production</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/distribute-your-apps/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Distribute via console</div></span></span></a></ul></ul></div></li><li class="sc-jGFFOr iJfdrZ"><div class="sc-hZeNU dZmoXu">Build</div><style data-emotion="css 1dlapeh">.css-1dlapeh{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:static;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;}</style><div class="css-1dlapeh"><ul class="sc-cSYcjD EsMfL"><style data-emotion="css 8zknns">.css-8zknns{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;}</style><div class="css-8zknns"><style data-emotion="css lzie5a 1cy6ofv 5mekwu">.css-lzie5a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-lzie5a::-moz-focus-inner{border:0;}.css-lzie5a:hover{-webkit-text-decoration:none;text-decoration:none;}.css-lzie5a:visited{color:currentColor;}.css-lzie5a:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-lzie5a:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-1cy6ofv{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-1cy6ofv::-moz-focus-inner{border:0;}.css-1cy6ofv:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1cy6ofv:visited{color:currentColor;}.css-1cy6ofv:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-1cy6ofv:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-5mekwu{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><style data-emotion="css 38t7l3 vbpl3">.css-38t7l3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-38t7l3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-vbpl3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-vbpl3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3::-moz-focus-inner{border:0;}.css-vbpl3:hover{-webkit-text-decoration:none;text-decoration:none;}.css-vbpl3:visited{color:currentColor;}.css-vbpl3:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-vbpl3:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}</style><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><style data-emotion="css fdr7fn">.css-fdr7fn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:var(--ds-scale-150, 12px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><span data-item-elem-before="true" class="css-fdr7fn"><style data-emotion="css 3zleef">.css-3zleef{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;text-align:center;-webkit-transform:none;-moz-transform:none;-ms-transform:none;transform:none;}</style><div class="css-3zleef"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><style data-emotion="css 1gly9cj">.css-1gly9cj{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;line-height:1.22;outline:none;overflow:hidden;text-align:left;}</style><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css 1mgvn46">.css-1mgvn46{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;font-size:14px;line-height:20px;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center;white-space:normal;color:var(--ds-text-subtle, #42526E);}</style><div class="css-1mgvn46">Development life cycle</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/getting-started/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css jv18ke">.css-jv18ke{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;white-space:normal;overflow:visible;color:var(--ds-text-subtle, #42526E);word-wrap:break-word;text-align:left;box-sizing:border-box;overflow-wrap:break-word;font-size:14px;font-weight:400;line-height:20px;}</style><div class="css-jv18ke">Developing with Forge</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/environments-and-versions/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Environment configuration</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Contributors</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/contributors/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/manage-app-contributors/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Managing contributors</div></span></span></a></ul><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/versions/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">App versions</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Testing and debugging</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/debugging/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/debug-functions-using-intellij/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Debug using IntelliJ</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/debug-functions-using-vscode/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Debug using VS Code</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/tunneling/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Tunneling</div></span></span></a></ul></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">App capabilities</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Compute</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Functions</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/function-reference/index/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Invoke functions</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/apis-reference/product-rest-api-reference/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call a product REST API</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/apis-reference/fetch-api-product.requestgraph/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call a product GraphQL API</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/authorize-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Verify user permissions for product APIs</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/external-fetch-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call an external REST API</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/authorize-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Check user account status</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/legacy-runtime-migrating/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Migrate from the legacy runtime</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Remotes</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/essentials/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge remote essentials</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/sending-product-events/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Send events to a remote</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/scheduled-triggers/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Schedule triggers to invoke a remote</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/accessing-storage/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Access Forge storage from a remote</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/calling-product-apis/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call product APIs from a remote</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/calling-from-frontend/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call from a Forge frontend</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/calling-from-function/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Call from a Forge function</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/bitbucket-git-operations/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Bitbucket git operations from a remote</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/observability/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Remote observability</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/remote/setup-dare-storage/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Setting up remotes for realm pinning</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Web triggers</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/web-trigger/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Work with web triggers</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Queues</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/runtime-reference/async-events-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Use async app event queues</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Events</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/events/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Platform and product events</div></span></span></a></ul><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/function-reference/index/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Reference</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Storage</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/runtime-reference/storage-api-basic/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Key value store</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/storage-reference/storage-api-custom-entities/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Entity store</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/storage-reference/sql/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">SQL (Preview)</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/storage-reference/storage-cache-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Cache (EAP)</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/runtime-reference/storage-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Reference</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/storage-reference/hosted-storage-data-lifecycle/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Hosted storage data lifecycle</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">User interface</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/ui-kit/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">UI Kit</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/apis-reference/ui-api-bridge/bridge/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Frontend bridge</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/manifest-reference/display-conditions/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Display conditions</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/ui-kit/overview/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Reference</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Observability</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/remote/observability/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/app-observability-in-third-party-tools" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">App observability in third-party tools</div></span></span></a></ul><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/automation-with-forge/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Automation with Forge</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Trust and security</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/data-residency/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Data residency</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Configuring app security</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/access-to-forge-apps-for-unlicensed-jsm-users/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Unlicensed user app access</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/add-scopes-to-call-an-atlassian-rest-api/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Scopes to call an Atlassian REST API</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/runtime-egress-permissions/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Runtime egress permissions</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/add-content-security-and-egress-controls/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Content security and egress controls</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/app-context-security/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">App context security</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV jjvRrZ css-vbpl3" leftPaddingSize="2" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">External authentication overview</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/use-an-external-oauth-2.0-api-with-fetch/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Configuring OAuth 2.0 providers</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/rotating-an-oauth-2.0-client-id-and-secret/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Rotating an OAuth 2.0 client ID and secret</div></span></span></a><a class="sc-dOkuiw kKjlYb css-vbpl3" leftPaddingSize="3" href="/platform/forge/common-issues-with-external-authentication/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Common issues with external authentication</div></span></span></a></ul></ul><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/runs-on-atlassian/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Runs on Atlassian</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Enterprise development</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/enterprise/use-forge-cli-on-corporate-network/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Using Forge CLI on a corporate network</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Forge releases and deprecation policy</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/whats-coming/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge releases (includes enrolling in EAP)</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/deprecation-policy/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge deprecation policy</div></span></span></a></ul></ul></div></li><li class="sc-jGFFOr iJfdrZ"><div class="sc-hZeNU dZmoXu">Manage</div><style data-emotion="css 1dlapeh">.css-1dlapeh{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:static;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;}</style><div class="css-1dlapeh"><ul class="sc-cSYcjD EsMfL"><style data-emotion="css lzie5a 1cy6ofv 5mekwu">.css-lzie5a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-lzie5a::-moz-focus-inner{border:0;}.css-lzie5a:hover{-webkit-text-decoration:none;text-decoration:none;}.css-lzie5a:visited{color:currentColor;}.css-lzie5a:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-lzie5a:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-1cy6ofv{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-1cy6ofv::-moz-focus-inner{border:0;}.css-1cy6ofv:hover{-webkit-text-decoration:none;text-decoration:none;}.css-1cy6ofv:visited{color:currentColor;}.css-1cy6ofv:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-1cy6ofv:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}.css-5mekwu{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}</style><style data-emotion="css 38t7l3 vbpl3">.css-38t7l3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-38t7l3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-38t7l3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;width:100%;min-height:var(--ds-scale-500, 40px);margin:var(--ds-scale-0, 0px);padding:var(--ds-scale-100, 8px) var(--ds-scale-250, 20px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;font-size:14px;outline:0;-webkit-text-decoration:none;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;color:currentColor;cursor:pointer;}.css-vbpl3:focus{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus-visible{outline-color:var(--ds-border-focused, #2684FF);outline-offset:-2px;outline-style:solid;outline-width:var(--ds-border-width-outline, 2px);}.css-vbpl3:focus:not(:focus-visible){outline:none;}@media screen and (forced-colors: active),screen and (-ms-high-contrast: active){.css-vbpl3:focus-visible{outline:1px solid;outline-offset:-1px;}}.css-vbpl3::-moz-focus-inner{border:0;}.css-vbpl3:hover{-webkit-text-decoration:none;text-decoration:none;}.css-vbpl3:visited{color:currentColor;}.css-vbpl3:hover{background-color:var(--ds-background-neutral-subtle-hovered, #F4F5F7);color:currentColor;}.css-vbpl3:active{background-color:var(--ds-background-neutral-subtle-pressed, #EBECF0);box-shadow:none;color:currentColor;}</style><a class="sc-dOkuiw dDqXHW css-vbpl3" leftPaddingSize="0" href="/platform/forge/manage-your-apps/" draggable="false" aria-disabled="false"><style data-emotion="css 1gly9cj">.css-1gly9cj{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;line-height:1.22;outline:none;overflow:hidden;text-align:left;}</style><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css jv18ke">.css-jv18ke{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;white-space:normal;overflow:visible;color:var(--ds-text-subtle, #42526E);word-wrap:break-word;text-align:left;box-sizing:border-box;overflow-wrap:break-word;font-size:14px;font-weight:400;line-height:20px;}</style><div class="css-jv18ke">Overview</div></span></span></a><style data-emotion="css 8zknns">.css-8zknns{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;}</style><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><style data-emotion="css fdr7fn">.css-fdr7fn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-right:var(--ds-scale-150, 12px);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}</style><span data-item-elem-before="true" class="css-fdr7fn"><style data-emotion="css 3zleef">.css-3zleef{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;text-align:center;-webkit-transform:none;-moz-transform:none;-ms-transform:none;transform:none;}</style><div class="css-3zleef"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><style data-emotion="css 1mgvn46">.css-1mgvn46{box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;border:none;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;font-size:14px;line-height:20px;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center;white-space:normal;color:var(--ds-text-subtle, #42526E);}</style><div class="css-1mgvn46">Observability</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Manage app alerts</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/alerts/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/create-alert-rules/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Create alert rules</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/manage-alert-rules/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Manage alert rules</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/view-open-and-closed-alerts/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">View open and closed alerts</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Monitor app metrics</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-app-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-invocation-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Monitor invocation metrics</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-api-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Monitor API metrics</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-cache-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Monitor cache metrics (EAP)</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-sql-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Monitor SQL (Preview)</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-usage-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Monitor usage metrics</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/export-app-metrics/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Export app metrics</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Monitor app logs</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/monitor-app-logs/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Overview</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/view-app-logs/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">View app logs</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/export-app-logs/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Export app logs</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/access-app-logs/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Access app logs</div></span></span></a></ul><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/view-app-installations/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">View app installations</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/view-app-storage/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">View app storage</div></span></span></a></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Access</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/manage-app-contributors/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Manage app contributors</div></span></span></a><div class="css-8zknns"><button class="sc-gjAXCV hiBcEo css-vbpl3" leftPaddingSize="1" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Manage environments</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/environments-and-versions/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Forge environments</div></span></span></a><a class="sc-dOkuiw kyARPC css-vbpl3" leftPaddingSize="2" href="/platform/forge/manifest-reference/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Configuring the manifest</div></span></span></a></ul></ul><div class="css-8zknns"><button class="sc-gjAXCV fEiqUH css-vbpl3" leftPaddingSize="0" type="button"><span data-item-elem-before="true" class="css-fdr7fn"><div class="css-3zleef"><span role="img" aria-label="open" style="--icon-primary-color:#B3BAC5;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M10.294 9.698a.988.988 0 010-1.407 1.01 1.01 0 011.419 0l2.965 2.94a1.09 1.09 0 010 1.548l-2.955 2.93a1.01 1.01 0 01-1.42 0 .988.988 0 010-1.407l2.318-2.297-2.327-2.307z" fill="currentColor" fill-rule="evenodd"/></svg></span></div></span><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-1mgvn46">Distribution</div></span></span></button></div><ul class="sc-cSYcjD gjDNHe"><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="https://developer.atlassian.com/platform/marketplace/listing-forge-apps/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Marketplace</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/distribute-your-apps/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">Distribute via console</div></span></span></a><a class="sc-dOkuiw kFokHU css-vbpl3" leftPaddingSize="1" href="/platform/forge/cli-reference/install/" draggable="false" aria-disabled="false"><span class="css-1gly9cj"><span class="css-5mekwu" data-item-title="true"><div class="css-jv18ke">CLI installation</div></span></span></a></ul></ul></div></li></ul></nav><div class="sc-fjNYmT cRavQB"><div class="sc-hzOKmB gWIkLp"><div class="sc-grYksN jGqvBW"><span class="sc-frudsx hsaQyA"><span class="sc-cBXKeB bWkibq">Last updated Oct 30, 2024</span></span></div></div><div class="sc-hdNmWC huMuzN"><div class="sc-imDdex hYifdp"><div class="sc-cBrjTV crKIBs"><h1 id="use-forge-hosted-storage-in-a-confluence-macro">Use Forge hosted storage in a Confluence macro<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h1><div class="sc-lffWgi iLIKSx"><div class="sc-fGSyRc eysgIS" width="192"><div class="sc-jkPxnQ cLWHVF"></div></div></div><p>This tutorial describes how to build an app for sharing definitions for terminology and acronyms across an entire Confluence site. The app uses Forge hostes storage to store definitions, which allows them to be shared between several macros and accessed from the site administration.</p> <p>In this tutorial you will learn how to persist and retrieve data from Forge hosted storage (specifically, the <a href="/platform/forge/runtime-reference/storage-api" target="_self">Key-Value Store</a>) and display the results in a table.</p> <div class="sc-hkaZBZ bsbZCT"><section class="sc-giOsra cWyolX"><div class="sc-jOVcOr ccUuQb"><style data-emotion="css snhnyn">.css-snhnyn{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;}.css-snhnyn &gt;svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-snhnyn &gt;svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-snhnyn &gt;svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}</style><span aria-hidden="true" style="--icon-primary-color:#006644;--icon-secondary-color:#E3FCEF" class="css-snhnyn"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M11.998 4A5.997 5.997 0 006 9.998c0 2.218 2.288 4.484 2.288 4.484.39.387.71 1.112.71 1.611 0 .499.45.907 1 .907h4c.55 0 1-.408 1-.907 0-.499.32-1.224.71-1.611 0 0 2.288-2.266 2.288-4.484A5.997 5.997 0 0011.998 4zm2.965 15c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v.003c0 .55.45 1 1 1h4c.55 0 1-.45 1-1V19z" fill="currentColor" fill-rule="evenodd"></path></svg></span></div><div class="sc-SFOxd KLVHW"><div class="sc-dzOgQY RfwMt"> <p>This tutorial has an accompanying <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/master/" target="_blank">Bitbucket repository<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a>. You&#x27;ll find a link to a git tag at the end of each step which you can use to compare with your code or to skip ahead.</p> <p>If you are cloning this repository, use <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>forge register</code></span></span> before you begin to create a new ID for the app under your account.</p> </div></div></section></div> <h2 id="before-you-begin">Before you begin<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p>This tutorial assumes you&#x27;re already familiar with the basics of Forge development. If this is your first time using Forge, see <a href="/platform/forge/getting-started/" target="_self">Getting started</a> first.</p> <p>To complete this tutorial, you need the latest version of Forge CLI. To update your CLI version, run <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>npm install -g @forge/cli@latest</code></span></span> on the command line.</p> <h3 id="set-up-a-cloud-developer-site">Set up a cloud developer site<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h3> <!-- --> <p>An Atlassian cloud developer site lets you install and test your app on Confluence and Jira products set up for you. If you don&#x27;t have one yet, set it up now:</p> <ol> <li>Go to <a href="http://go.atlassian.com/cloud-dev" target="_blank">http://go.atlassian.com/cloud-dev<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> and create a site using the email address associated with your Atlassian account.</li> <li>Once your site is ready, log in and complete the setup wizard.</li> </ol> <p>You can install your app to multiple Atlassian sites. However, app data won&#x27;t be shared between separate Atlassian sites, products, or Forge environments.</p> <p>The limits on the numbers of users you can create are as follows:</p> <ul> <li>Confluence: 5 users</li> <li>Jira Service Management: 1 agent</li> <li>Jira Software and Jira Work Management: 5 users</li> </ul> <div class="sc-hkaZBZ bsbZCT"><section class="sc-giOsra hEREHr"><div class="sc-jOVcOr ccUuQb"><style data-emotion="css snhnyn">.css-snhnyn{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;}.css-snhnyn &gt;svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-snhnyn &gt;svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-snhnyn &gt;svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}</style><span aria-hidden="true" style="--icon-primary-color:#FF8B00;--icon-secondary-color:#FFFAE6" class="css-snhnyn"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill-rule="evenodd"><path d="M12.938 4.967c-.518-.978-1.36-.974-1.876 0L3.938 18.425c-.518.978-.045 1.771 1.057 1.771h14.01c1.102 0 1.573-.797 1.057-1.771L12.938 4.967z" fill="currentColor"></path><path d="M12 15a1 1 0 01-1-1V9a1 1 0 012 0v5a1 1 0 01-1 1m0 3a1 1 0 010-2 1 1 0 010 2" fill="inherit"></path></g></svg></span></div><div class="sc-SFOxd KLVHW"><div class="sc-dzOgQY RfwMt"> <p>The Atlassian Marketplace doesn&#x27;t currently support cross-product apps. If your app supports multiple products, you can publish two separate listings on the Marketplace, but your app won&#x27;t be able to make API calls across different products and instances/installations.</p> </div></div></section></div> <h2 id="step-1--create-your-app">Step 1: Create your app<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p>Create an app based on the Hello world template. Using your terminal complete the following:</p> <ol> <li> <p>Navigate to the directory where you want to create the app.</p> </li> <li> <p>Create your app by running:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="shell">forge create </code></pre></div></div></div></div></pre> </li> <li> <p>Enter a name for the app. For example, <em>definitions-macro</em>.</p> </li> <li> <p>Select the <em>UI Kit</em> category.</p> </li> <li> <p>Select the <em>Confluence</em> product.</p> </li> <li> <p>Select the <em>confluence-macro</em> template.</p> </li> <li> <p>Your app has been created in a directory with the same name as your app, for example <em>definitions-macro</em>. Open the app directory to see the files associated with your app.</p> </li> <li> <p>Install the latest version of the Forge API package</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="shell">npm install --save @forge/api@latest </code></pre></div></div></div></div></pre> </li> <li> <p>Enable the Key-Value Store by adding the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>storage:app</code></span></span> scope to the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>manifest.yml</code></span></span> file. [Learn more about adding scopes to call an Atlassian REST API] (/platform/forge/add-scopes-to-call-an-atlassian-rest-api/).</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="yaml">permissions: scopes: - storage:app </code></pre></div></div></div></div></pre> </li> <li> <p>Enable the <a href="https://developer.atlassian.com/platform/forge/add-configuration-to-a-macro-with-ui-kit/" target="_self">config</a> so that it can appear in the macro by adding <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>config: true</code></span></span> under <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>macro</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="yaml">modules: macro: ... config: true </code></pre></div></div></div></div></pre> </li> </ol> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-1/" target="_blank">step 1<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="step-2--deploy-and-install-your-app">Step 2: Deploy and install your app<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <ol> <li> <p>Navigate to the app&#x27;s top-level directory and deploy your app by running:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="shell">forge deploy </code></pre></div></div></div></div></pre> </li> <li> <p>Install your app by running:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="shell">forge install </code></pre></div></div></div></div></pre> </li> <li> <p>Select your Atlassian product using the arrow keys and press the enter key.</p> </li> <li> <p>Enter the URL for your development site. For example, <em>example.atlassian.net</em>. <a href="https://admin.atlassian.com/" target="_blank">View a list of your active sites at Atlassian administration<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a>.</p> </li> </ol> <p>Once the <em>successful installation</em> 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 <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>forge uninstall</code></span></span> command.</p> <div class="sc-hkaZBZ bsbZCT"><section class="sc-giOsra cEicjz"><div class="sc-jOVcOr ccUuQb"><style data-emotion="css snhnyn">.css-snhnyn{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;}.css-snhnyn &gt;svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-snhnyn &gt;svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-snhnyn &gt;svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}</style><span aria-hidden="true" style="--icon-primary-color:#0747A6;--icon-secondary-color:#DEEBFF" class="css-snhnyn"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill-rule="evenodd"><path d="M2 12c0 5.523 4.477 10 10 10s10-4.477 10-10S17.523 2 12 2 2 6.477 2 12z" fill="currentColor"></path><rect fill="inherit" x="11" y="10" width="2" height="7" rx="1"></rect><circle fill="inherit" cx="12" cy="8" r="1"></circle></g></svg></span></div><div class="sc-SFOxd KLVHW"><div class="sc-dzOgQY RfwMt"> <p>Running the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>forge install</code></span></span> 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 <a href="/platform/marketplace/listing-forge-apps/#what-if-my-app-supports-multiple-products-" target="_self">does not support cross-product apps yet</a>.</p> <p>You must run <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>forge deploy</code></span></span> before running <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>forge install</code></span></span> in any of the Forge environments.</p> </div></div></section></div> <p>Next, add your new Confluence macro to a page. To view log invocations, start a <a href="/platform/forge/tunneling/" target="_self">tunnel</a> to your app:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="text">forge tunnel </code></pre></div></div></div></div></pre> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-2/" target="_blank">step 2<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="step-3--add-a-configuration-dialog-to-the-macro">Step 3: Add a configuration dialog to the macro<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <ol> <li> <p>Within the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/index.jsx</code></span></span> file, add a new component named <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Config</code></span></span> containing <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/text-area/" target="_self">TextArea</a> and Label from the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>@forge/react</code></span></span> library. This configuration form allows a user of the macro to specify a set of definitions to show in a table.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const Config = () =&gt; { return ( &lt;&gt; &lt;Label labelFor=&quot;terms&quot;&gt;Terms to include (one per line)&lt;/Label&gt; &lt;TextArea name=&quot;terms&quot; id=&quot;terms&quot; defaultValue=&quot;&quot; isRequired /&gt; &lt;/&gt; ) }; </code></pre></div></div></div></div></pre> </li> <li> <p>Add the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Config</code></span></span> function to the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>ForgeReconciler</code></span></span> to allow for configuration changes, under the existing <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>ForgeReconciler.render()</code></span></span> for <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>App</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">ForgeReconciler.render( &lt;React.StrictMode&gt; &lt;App /&gt; &lt;/React.StrictMode&gt; ); ForgeReconciler.addConfig(&lt;Config /&gt;); </code></pre></div></div></div></div></pre> </li> <li> <p>Add the <a href="https://developer.atlassian.com/platform/forge/ui-kit/hooks/use-config/" target="_self"><span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>useConfig</code></span></span></a> hook to the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>App</code></span></span> component. This hook allows the app to access configuration set by the user in the macro configuration dialog, and defaults to an empty object if undefined. If there is no list of terms found in config, <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>terms</code></span></span> defaults to an empty array. App currently returns the information wrapped in the <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/text/" target="_self">Text</a> component.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const App = () =&gt; { const config = useConfig() || {}; const terms = config.terms ? config.terms.split(&quot;\n&quot;) : []; if (terms.length === 0) { return ( &lt;Text&gt;No Terms&lt;/Text&gt; ); } return ( &lt;Text&gt;{terms.join(&quot;,&quot;)}&lt;/Text&gt; ); }; </code></pre></div></div></div></div></pre> </li> </ol> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-3/" target="_blank">step 3<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="step-4--fetch-a-list-of-definitions-from-storage">Step 4: Fetch a list of definitions from storage<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p>Your app makes use of the JavaScript API provided in the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>@forge/api</code></span></span> package to interact with the Key-Value Store. This package provides methods for reading, writing, and querying data within the Key-Value Store.</p> <p>This tutorial starts with reading a list of definitions from the Key-Value Store. Initially the results are empty; adding definitions is covered in a later stage.</p> <p>The app stores key entities based on the term, with the following format:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="typescript">interface Term { definition: string; term: string; } </code></pre></div></div></div></div></pre> <ol> <li> <p>Within <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/resolvers/index.js</code></span></span>, add a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>getDefinition</code></span></span> function to load a definition given a term.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">import Resolver from &#x27;@forge/resolver&#x27;; import { storage } from &#x27;@forge/api&#x27;; const resolver = new Resolver(); // Create a key composed from the term function termKey(term) { return `term-${term}`; } async function getDefinition(term) { const value = await storage.get(termKey(term)); return value ? value.definition : &quot;&quot;; } export const handler = resolver.getDefinitions(); </code></pre></div></div></div></div></pre> </li> <li> <p>Also create a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>getDefinitions</code></span></span> function using <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>resolver</code></span></span> to turn a list of terms into a list of definitions.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">resolver.define(&#x27;getDefinitions&#x27;, async(req) =&gt; { const pendingDefinitions = req.payload.terms.map((term) =&gt; getDefinition(term)); return await Promise.all(pendingDefinitions); }) </code></pre></div></div></div></div></pre> <div class="sc-hkaZBZ bsbZCT"><section class="sc-giOsra cEicjz"><div class="sc-jOVcOr ccUuQb"><style data-emotion="css snhnyn">.css-snhnyn{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;}.css-snhnyn &gt;svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-snhnyn &gt;svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-snhnyn &gt;svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}</style><span aria-hidden="true" style="--icon-primary-color:#0747A6;--icon-secondary-color:#DEEBFF" class="css-snhnyn"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill-rule="evenodd"><path d="M2 12c0 5.523 4.477 10 10 10s10-4.477 10-10S17.523 2 12 2 2 6.477 2 12z" fill="currentColor"></path><rect fill="inherit" x="11" y="10" width="2" height="7" rx="1"></rect><circle fill="inherit" cx="12" cy="8" r="1"></circle></g></svg></span></div><div class="sc-SFOxd KLVHW"><div class="sc-dzOgQY RfwMt"> <p>This function makes use of the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Promise.all</code></span></span> operation to turn a list of pending promises into a single promise. The resulting promise resolves to an array of definitions when awaited.</p> </div></div></section></div> </li> <li> <p>Inside the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/index.jsx</code></span></span> file, add a new hook within the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>App</code></span></span> component for <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>definitions</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const [definitions, setDefinitions] = useState([]); </code></pre></div></div></div></div></pre> </li> <li> <p>In the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/index.jsx</code></span></span> file, define an async helper function called <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>populateDefinitions</code></span></span> inside the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>App</code></span></span> component using <a href="https://developer.atlassian.com/platform/forge/ui-kit-hooks-reference/#useeffect" target="_self">useEffect</a>. This invokes the resolver with key <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>getDefinitions</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript"> useEffect(() =&gt; { const populateDefinitions = async() =&gt; { if (terms.length !== 0) { const data = await invoke(&#x27;getDefinitions&#x27;, { terms: terms }); setDefinitions(data); } } populateDefinitions(); }, [terms, invoke, setDefinitions]); </code></pre></div></div></div></div></pre> </li> <li> <p>Change the return of the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>App</code></span></span> component to load the definitions for the provided terms list. Since no definitions have been provided yet, definitions should be empty.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const App = () =&gt; { const [definitions, setDefinitions] = useState([]); const config = useConfig() || {}; const terms = config.terms ? config.terms.split(&quot;\n&quot;) : []; useEffect(() =&gt; { const populateDefinitions = async() =&gt; { if (terms.length !== 0) { const data = await invoke(&#x27;getDefinitions&#x27;, { terms: terms }); setDefinitions(data); } } populateDefinitions(); }, [terms, invoke, setDefinitions]); return ( &lt;&gt; &lt;Text&gt;{terms.join(&quot;,&quot;)}&lt;/Text&gt; &lt;Text&gt;{definitions.join(&quot;,&quot;)}&lt;/Text&gt; &lt;/&gt; ); }; </code></pre></div></div></div></div></pre> </li> </ol> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-4/" target="_blank">step 4<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="step-5--create-the-definitions-table">Step 5: Create the definitions table<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p><img class="sc-cmIlrE kiIrR" src="https://dac-static.atlassian.com/platform/forge/images/definition-macro-step-5.png?_v=1.5800.1062" alt="The definition table"/></p> <p>In this step, you&#x27;ll add a <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/dynamic-table/" target="_self">Dynamic Table</a> to the definitions macro to show the list of terms side by side with a list of definitions.</p> <p>It can be useful when building a UI Kit app to group elements together into reusable components. For this app, we will add a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span> component.</p> <ol> <li> <p>Create a new file named <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>definition-table.jsx</code></span></span> in <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend</code></span></span>.</p> </li> <li> <p>In this file, create a component named <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span>. This component renders a list of definitions in a table. Also add an object called <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>head</code></span></span>, which will contain the data for the headers of <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span>. Also remember to import <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>invoke</code></span></span> for later.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">import React from &#x27;react&#x27;; import { DynamicTable } from &quot;@forge/react&quot;; import { invoke } from &#x27;@forge/bridge&#x27;; // Render the table headers const head = { cells: [ { key: &quot;term&quot;, content: &quot;Term&quot;, isSortable: true, }, { key: &quot;definition&quot;, content: &quot;Definition&quot;, shouldTruncate: true, isSortable: true, }, { key: &quot;buttons&quot;, // Additional column for buttons on each row content: &quot;&quot;, shouldTruncate: true, isSortable: true, }, ], }; // Render the Definition Table export const DefinitionTable = ({ terms, definitions }) =&gt; { return ( &lt;DynamicTable head={head} emptyView=&quot;No terms provided, please press Edit on the app and add terms in the Configuration box&quot; /&gt; ); }; </code></pre></div></div></div></div></pre> </li> <li> <p>In the same file, add an object called <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>row</code></span></span> - this will be used to render each row in the definitions table. Also add a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>createKey</code></span></span> function that generates a key for each term in the row.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">// create a key for each term const createKey = (input) =&gt; { return input ? input.replace(/\s/g, &quot;&quot;) : input; // remove whitespace } // Render the Definition Table export const DefinitionTable = ({ terms, definitions }) =&gt; { const rows = terms.map((term, index) =&gt; ({ key: `row-${index}-${term}`, cells: [ { key: createKey(term), content: term }, { key: index, content: definitions[index], colSpan: 2, }, ], })); return ( &lt;DynamicTable head={head} rows={rows} emptyView=&quot;No terms provided, please press Edit on the app and add terms in the Configuration box&quot; /&gt; ); } </code></pre></div></div></div></div></pre> </li> <li> <p>Add an import for the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span> component in <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/index.jsx</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">import { DefinitionTable } from &#x27;./definition-table&#x27;; </code></pre></div></div></div></div></pre> </li> <li> <p>Add this table to your existing macro in <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/index.jsx</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">return ( &lt;&gt; &lt;DefinitionTable terms={terms} definitions={definitions}/&gt; &lt;/&gt; ); </code></pre></div></div></div></div></pre> </li> </ol> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-5/" target="_blank">step 5<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="step-6--allow-a-user-to-add-a-definition">Step 6: Allow a user to add a definition<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p><img class="sc-cmIlrE kiIrR" src="https://dac-static.atlassian.com/platform/forge/images/definition-macro-step-6a.png?_v=1.5800.1062" alt="The usable definition table"/></p> <p>At this stage, there&#x27;s still no data stored for the app. In this step, you&#x27;ll add the ability to store a definition for a term.</p> <ol> <li> <p>Add a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>saveDefinition</code></span></span> method to the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/resolvers/index.js</code></span></span> file.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">resolver.define(&#x27;saveDefinition&#x27;, async(req) =&gt; { const { term, definition } = req.payload; await storage.set(termKey(term), { term, definition }); }) </code></pre></div></div></div></div></pre> </li> <li> <p>Add a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>removeDefinition</code></span></span> method to the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/resolvers/index.js</code></span></span> file.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">resolver.define(&#x27;removeDefinition&#x27;, async(req) =&gt; { let term = req.payload.term; await storage.delete(termKey(term)); }) </code></pre></div></div></div></div></pre> </li> <li> <p>In <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>src/frontend/definition-table.jsx</code></span></span>, within the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span> component, set up React hooks that will be used to open an input modal. This enables a user to provide a definition for a term.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const { handleSubmit, register, getFieldId } = useForm(); const [term, setTerm] = useState(&#x27;&#x27;); const [definition, setDefinition] = useState(&#x27;&#x27;); const [loadingState, setLoadingState] = useState(false); const [inputIsOpen, setInputIsOpen] = useState(false); const openInputModal = () =&gt; setInputIsOpen(true); const closeInputModal = () =&gt; setInputIsOpen(false); </code></pre></div></div></div></div></pre> </li> <li> <p>Also set up React hooks that will be used to open a delete confirmation modal as well. This enables a user to delete a provided definition for a term.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const [deleteIsOpen, setDeleteIsOpen] = useState(false); const openDeleteModal = () =&gt; setDeleteIsOpen(true); const closeDeleteModal = () =&gt; setDeleteIsOpen(false); </code></pre></div></div></div></div></pre> </li> <li> <p>Add two <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/modal/" target="_self">Modals</a> in the return statement of the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span> component. When the user clicks submit for the input modal, the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>saveDefinition</code></span></span> resolver callback is invoked in the <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/form/" target="_self">Form</a> component and then the modal closed. When the user clicks submit for the delete modal, the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>removeDefinition</code></span></span> resolver callback is invoked.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">return ( &lt;&gt; &lt;DynamicTable head={head} rows={rows} emptyView=&quot;No terms provided, please press Edit on the app and add terms in the Configuration box&quot; isLoading={loadingState} /&gt; &lt;ModalTransition&gt; {inputIsOpen &amp;&amp; ( &lt;Modal onClose={closeInputModal}&gt; &lt;Form onSubmit={handleSubmit(submitInput)} &gt; &lt;ModalHeader&gt; &lt;ModalTitle&gt;{`Add definition for ${term}`}&lt;/ModalTitle&gt; &lt;/ModalHeader&gt; &lt;ModalBody&gt; &lt;Label labelFor={getFieldId(&quot;definition&quot;)}&gt;{`Definition for ${term}`}&lt;/Label&gt; &lt;TextArea name=&quot;definition&quot; id=&quot;definition&quot; defaultValue={definition} {...register(&quot;definition&quot;, { required: true })} /&gt; &lt;/ModalBody&gt; &lt;ModalFooter&gt; &lt;Button appearance=&quot;subtle&quot; onClick={closeInputModal}&gt; Cancel &lt;/Button&gt; &lt;Button appearance=&quot;primary&quot; onClick={closeInputModal} type=&quot;submit&quot;&gt; Submit &lt;/Button&gt; &lt;/ModalFooter&gt; &lt;/Form&gt; &lt;/Modal&gt; )} &lt;/ModalTransition&gt; &lt;ModalTransition&gt; {deleteIsOpen &amp;&amp; ( &lt;Modal onClose={closeDeleteModal}&gt; &lt;Form onSubmit={handleSubmit(submitDelete)} &gt; &lt;ModalHeader&gt; &lt;ModalTitle&gt;{`Delete definition for ${term}?`}&lt;/ModalTitle&gt; &lt;/ModalHeader&gt; &lt;ModalFooter&gt; &lt;Button appearance=&quot;subtle&quot; onClick={closeDeleteModal}&gt; Cancel &lt;/Button&gt; &lt;Button appearance=&quot;danger&quot; onClick={closeDeleteModal} type=&quot;submit&quot;&gt; Delete &lt;/Button&gt; &lt;/ModalFooter&gt; &lt;/Form&gt; &lt;/Modal&gt; )} &lt;/ModalTransition&gt; &lt;/&gt; ); </code></pre></div></div></div></div></pre> </li> <li> <p>Add two submit functions for the input and delete modals respectively within the <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>DefinitionTable</code></span></span> component.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const submitInput = async({ definition }) =&gt; { setLoadingState(true); await invoke(&#x27;saveDefinition&#x27;, { term: term, definition: definition }) setLoadingState(false); }; const submitDelete = async() =&gt; { setLoadingState(true); await invoke(&#x27;removeDefinition&#x27;, { term: term }) setLoadingState(false); }; </code></pre></div></div></div></div></pre> </li> <li> <p>Create a <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>generateRow</code></span></span> function that uses <a href="https://developer.atlassian.com/platform/forge/ui-kit/#supported-hook-types" target="_self">useCallback</a>. This will return the definition of a term if it exists, along with an <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Edit</code></span></span> and <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Delete</code></span></span> button for modifying the definition. This is formatted using <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/inline/" target="_self">Inline</a>. If the definition for the term does not exist, it will render an <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>Add Definition</code></span></span> button. Otherwise, it will render a <a href="https://developer.atlassian.com/platform/forge/ui-kit/components/spinner/" target="_self">Spinner</a>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const generateRow = useCallback( (index, term, generatedDefinition) =&gt; { let definitionContent = &lt;Spinner /&gt;; if (generatedDefinition === &quot;&quot;) { definitionContent = &lt;Button appearance=&quot;default&quot; onClick={() =&gt; { setTerm(term); setDefinition(&quot;&quot;); openInputModal(); }}&gt; Add Definition &lt;/Button&gt; } else if (generatedDefinition) { definitionContent = &lt;Inline spread=&quot;space-between&quot;&gt; &lt;Text&gt;{generatedDefinition}&lt;/Text&gt; &lt;ButtonGroup&gt; &lt;Button appearance=&quot;default&quot; spacing=&quot;compact&quot; onClick={() =&gt; { setTerm(term); setDefinition(generatedDefinition); openInputModal(); }}&gt; Edit &lt;/Button&gt; &lt;Button appearance=&quot;danger&quot; spacing=&quot;compact&quot; onClick={() =&gt; { setTerm(term); openDeleteModal(); }}&gt; Delete &lt;/Button&gt; &lt;/ButtonGroup&gt; &lt;/Inline&gt; } return ({ key: `row-${index}-${term}`, cells: [ { key: createKey(term), content: term }, { key: index, content: definitionContent, colSpan: 2, }, ], }) }, [setTerm, setDefinition, openInputModal, openDeleteModal, createKey, setTerm, setDefinition, openInputModal, openDeleteModal]); </code></pre></div></div></div></div></pre> </li> <li> <p>Add <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>generateRow</code></span></span> function to the rows variable, so it will be rendered in <span class="sc-jdeSqf cQNBrn"><span style="font-family:function () { return &quot;&#x27;SFMono-Medium&#x27;, &#x27;SF Mono&#x27;, &#x27;Segoe UI Mono&#x27;, &#x27;Roboto Mono&#x27;, &#x27;Ubuntu Mono&#x27;, Menlo, Consolas, Courier, monospace&quot;; };font-size:inherit;background:#F4F5F7;color:#172B4D;border-radius:3px;display:inline;overflow-x:auto;white-space:pre-wrap;padding:2px 4px;line-height:inherit"><code>&lt;DynamicTable&gt;</code></span></span>.</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="javascript">const rows = terms.map((term, index) =&gt; ( generateRow(index, term, definitions[index]) )); </code></pre></div></div></div></div></pre> </li> <li> <p>Stop tunneling your app and deploy it by running:</p> <pre><div class="sc-jGxEUC jCVVco"><div class="sc-cZBZkQ fypsmc"><div class="sc-gbzWSY jgxetf"><div class="sc-jqIZGH vudGk"><pre>1 2</pre><pre><code class="shell">forge deploy </code></pre></div></div></div></div></pre> </li> </ol> <p>You can check your app against <a href="https://bitbucket.org/atlassian/definitions-macro-tutorial/src/step-6/" target="_blank">step 6<style data-emotion="css 1wits42">.css-1wits42{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:16px;height:16px;}.css-1wits42 >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1wits42 >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1wits42 >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1wits42 >svg{width:16px;height:16px;}</style><span role="img" aria-label="Follow" style="--icon-primary-color:currentColor;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1wits42"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M11.031 7A1.03 1.03 0 0010 8.036a1.05 1.05 0 001.044 1.045l3.121.014.014 3.121a1.05 1.05 0 001.045 1.044 1.03 1.03 0 001.036-1.035l-.019-4.161a1.053 1.053 0 00-1.045-1.045L11.035 7h-.004z"/><path d="M13.364 8.292l-7.072 7.071a1.002 1.002 0 000 1.415c.39.39 1.024.39 1.415 0l7.071-7.071A1.002 1.002 0 0014.071 8a1 1 0 00-.707.292z"/></g></svg></span></a> in the tutorial repository.</p> <h2 id="next-steps">Next steps<span role="presentation" class="heading-anchor-wrapper"><button class="sc-iCwjlJ bIjwqY"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span role="img" aria-label="copy" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><g fill="currentColor" fill-rule="evenodd"><path d="M12.856 5.457l-.937.92a1.002 1.002 0 000 1.437 1.047 1.047 0 001.463 0l.984-.966c.967-.95 2.542-1.135 3.602-.288a2.54 2.54 0 01.203 3.81l-2.903 2.852a2.646 2.646 0 01-3.696 0l-1.11-1.09L9 13.57l1.108 1.089c1.822 1.788 4.802 1.788 6.622 0l2.905-2.852a4.558 4.558 0 00-.357-6.82c-1.893-1.517-4.695-1.226-6.422.47"/><path d="M11.144 19.543l.937-.92a1.002 1.002 0 000-1.437 1.047 1.047 0 00-1.462 0l-.985.966c-.967.95-2.542 1.135-3.602.288a2.54 2.54 0 01-.203-3.81l2.903-2.852a2.646 2.646 0 013.696 0l1.11 1.09L15 11.43l-1.108-1.089c-1.822-1.788-4.802-1.788-6.622 0l-2.905 2.852a4.558 4.558 0 00.357 6.82c1.893 1.517 4.695 1.226 6.422-.47"/></g></svg></span></button></span></h2> <p>At this point your app is able display a list of terms and their associated definitions. The app stores definitions in the storage service, and shares these across all the instances of the macro in the site.</p> <p>Explore Forge storage in further detail over the following pages:</p> <ul> <li>Read <a href="/platform/forge/storage/" target="_self">App storage options</a> for an overview of the different ways Forge apps can store data</li> <li>Read about the <a href="/platform/forge/runtime-reference/storage-api" target="_self">Key-Value Store</a> which details the JavaScript API.</li> <li>Learn more about how <a href="/platform/forge/runtime-reference/storage-api-query" target="_self">Queries</a> can be run against data stored in the Key-Value Store.</li> <li>View the <a href="/platform/forge/platform-quotas-and-limits/#storage-quotas" target="_self">Limits</a> that apply to apps using Forge hosted storage.</li> </ul></div><div class="sc-dCVVYJ rJVhP"><div class="sc-hARARD hrxrbx"><p class="sc-ccLTTT gfLKuW">Rate this page:</p><style data-emotion-css="fwv93l">.css-fwv93l{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:0;}.css-fwv93l [data-rating-icon-checked]{display:inline-block;}.css-fwv93l [data-rating-icon]{display:none;}.css-fwv93l label:hover ~ label [data-rating-icon-checked][data-rating-icon-checked],.css-fwv93l input:checked ~ label [data-rating-icon-checked]{display:none;}.css-fwv93l label:hover ~ label [data-rating-icon][data-rating-icon],.css-fwv93l input:checked ~ label [data-rating-icon]{display:inline-block;}.css-fwv93l:hover [data-rating-icon-checked][data-rating-icon-checked]{display:inline-block;}.css-fwv93l:hover [data-rating-icon][data-rating-icon]{display:none;}</style><div class="css-fwv93l"><style data-emotion-css="i9qcsw">.css-i9qcsw{border:0 !important;-webkit-clip:rect(1px,1px,1px,1px) !important;clip:rect(1px,1px,1px,1px) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important;}</style><label for="rating-bottom--empty" class="css-i9qcsw"></label><input type="radio" id="rating-bottom--empty" name="rating-bottom" checked="" class="css-i9qcsw"/><label for="rating-bottom--0" style="transition:transform 100ms cubic-bezier(0.15,1,0.3,1)"><div role="presentation"><div><span class="css-i9qcsw">Unusable</span><span aria-hidden="true" data-rating-icon="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 16.373l3.98 2.193-.76-4.655 3.276-3.347-4.524-.69L12 5.687l-1.972 4.189-4.524.689L8.78 13.91l-.762 4.655L12 16.373zm0 2.283l-3.016 1.662a2 2 0 01-2.939-2.075l.599-3.656-2.57-2.624a2 2 0 011.129-3.377l3.47-.528 1.518-3.224a2 2 0 013.618 0l1.519 3.224 3.47.528a2 2 0 011.127 3.377l-2.569 2.624.599 3.656a2 2 0 01-2.94 2.075L12 18.656z" fill="currentColor"/></svg></span></span><span aria-hidden="true" data-rating-icon-checked="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12.072 17.284l-3.905 2.053a1 1 0 01-1.451-1.054l.745-4.349-3.159-3.08a1 1 0 01.554-1.705l4.366-.635 1.953-3.956a1 1 0 011.794 0l1.952 3.956 4.366.635a1 1 0 01.555 1.705l-3.16 3.08.746 4.349a1 1 0 01-1.45 1.054l-3.906-2.053z" fill="currentColor" fill-rule="evenodd"/></svg></span></span></div></div></label><input type="radio" id="rating-bottom--0" value="1" name="rating-bottom" class="css-i9qcsw"/><label for="rating-bottom--1" style="transition:transform 100ms cubic-bezier(0.15,1,0.3,1)"><div role="presentation"><div><span class="css-i9qcsw">Poor</span><span aria-hidden="true" data-rating-icon="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 16.373l3.98 2.193-.76-4.655 3.276-3.347-4.524-.69L12 5.687l-1.972 4.189-4.524.689L8.78 13.91l-.762 4.655L12 16.373zm0 2.283l-3.016 1.662a2 2 0 01-2.939-2.075l.599-3.656-2.57-2.624a2 2 0 011.129-3.377l3.47-.528 1.518-3.224a2 2 0 013.618 0l1.519 3.224 3.47.528a2 2 0 011.127 3.377l-2.569 2.624.599 3.656a2 2 0 01-2.94 2.075L12 18.656z" fill="currentColor"/></svg></span></span><span aria-hidden="true" data-rating-icon-checked="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12.072 17.284l-3.905 2.053a1 1 0 01-1.451-1.054l.745-4.349-3.159-3.08a1 1 0 01.554-1.705l4.366-.635 1.953-3.956a1 1 0 011.794 0l1.952 3.956 4.366.635a1 1 0 01.555 1.705l-3.16 3.08.746 4.349a1 1 0 01-1.45 1.054l-3.906-2.053z" fill="currentColor" fill-rule="evenodd"/></svg></span></span></div></div></label><input type="radio" id="rating-bottom--1" value="2" name="rating-bottom" class="css-i9qcsw"/><label for="rating-bottom--2" style="transition:transform 100ms cubic-bezier(0.15,1,0.3,1)"><div role="presentation"><div><span class="css-i9qcsw">Okay</span><span aria-hidden="true" data-rating-icon="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 16.373l3.98 2.193-.76-4.655 3.276-3.347-4.524-.69L12 5.687l-1.972 4.189-4.524.689L8.78 13.91l-.762 4.655L12 16.373zm0 2.283l-3.016 1.662a2 2 0 01-2.939-2.075l.599-3.656-2.57-2.624a2 2 0 011.129-3.377l3.47-.528 1.518-3.224a2 2 0 013.618 0l1.519 3.224 3.47.528a2 2 0 011.127 3.377l-2.569 2.624.599 3.656a2 2 0 01-2.94 2.075L12 18.656z" fill="currentColor"/></svg></span></span><span aria-hidden="true" data-rating-icon-checked="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12.072 17.284l-3.905 2.053a1 1 0 01-1.451-1.054l.745-4.349-3.159-3.08a1 1 0 01.554-1.705l4.366-.635 1.953-3.956a1 1 0 011.794 0l1.952 3.956 4.366.635a1 1 0 01.555 1.705l-3.16 3.08.746 4.349a1 1 0 01-1.45 1.054l-3.906-2.053z" fill="currentColor" fill-rule="evenodd"/></svg></span></span></div></div></label><input type="radio" id="rating-bottom--2" value="3" name="rating-bottom" class="css-i9qcsw"/><label for="rating-bottom--3" style="transition:transform 100ms cubic-bezier(0.15,1,0.3,1)"><div role="presentation"><div><span class="css-i9qcsw">Good</span><span aria-hidden="true" data-rating-icon="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 16.373l3.98 2.193-.76-4.655 3.276-3.347-4.524-.69L12 5.687l-1.972 4.189-4.524.689L8.78 13.91l-.762 4.655L12 16.373zm0 2.283l-3.016 1.662a2 2 0 01-2.939-2.075l.599-3.656-2.57-2.624a2 2 0 011.129-3.377l3.47-.528 1.518-3.224a2 2 0 013.618 0l1.519 3.224 3.47.528a2 2 0 011.127 3.377l-2.569 2.624.599 3.656a2 2 0 01-2.94 2.075L12 18.656z" fill="currentColor"/></svg></span></span><span aria-hidden="true" data-rating-icon-checked="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12.072 17.284l-3.905 2.053a1 1 0 01-1.451-1.054l.745-4.349-3.159-3.08a1 1 0 01.554-1.705l4.366-.635 1.953-3.956a1 1 0 011.794 0l1.952 3.956 4.366.635a1 1 0 01.555 1.705l-3.16 3.08.746 4.349a1 1 0 01-1.45 1.054l-3.906-2.053z" fill="currentColor" fill-rule="evenodd"/></svg></span></span></div></div></label><input type="radio" id="rating-bottom--3" value="4" name="rating-bottom" class="css-i9qcsw"/><label for="rating-bottom--4" style="transition:transform 100ms cubic-bezier(0.15,1,0.3,1)"><div role="presentation"><div><span class="css-i9qcsw">Excellent</span><span aria-hidden="true" data-rating-icon="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12 16.373l3.98 2.193-.76-4.655 3.276-3.347-4.524-.69L12 5.687l-1.972 4.189-4.524.689L8.78 13.91l-.762 4.655L12 16.373zm0 2.283l-3.016 1.662a2 2 0 01-2.939-2.075l.599-3.656-2.57-2.624a2 2 0 011.129-3.377l3.47-.528 1.518-3.224a2 2 0 013.618 0l1.519 3.224 3.47.528a2 2 0 011.127 3.377l-2.569 2.624.599 3.656a2 2 0 01-2.94 2.075L12 18.656z" fill="currentColor"/></svg></span></span><span aria-hidden="true" data-rating-icon-checked="true"><style data-emotion="css 1afrefi">.css-1afrefi{display:inline-block;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;line-height:1;width:24px;height:24px;}.css-1afrefi >svg{overflow:hidden;pointer-events:none;max-width:100%;max-height:100%;color:var(--icon-primary-color);fill:var(--icon-secondary-color);vertical-align:bottom;}.css-1afrefi >svg stop{stop-color:currentColor;}@media screen and (forced-colors: active){.css-1afrefi >svg{-webkit-filter:grayscale(1);filter:grayscale(1);--icon-primary-color:CanvasText;--icon-secondary-color:Canvas;}}.css-1afrefi >svg{width:24px;height:24px;}</style><span aria-hidden="true" style="--icon-primary-color:#6B778C;--icon-secondary-color:var(--ds-surface, #FFFFFF)" class="css-1afrefi"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M12.072 17.284l-3.905 2.053a1 1 0 01-1.451-1.054l.745-4.349-3.159-3.08a1 1 0 01.554-1.705l4.366-.635 1.953-3.956a1 1 0 011.794 0l1.952 3.956 4.366.635a1 1 0 01.555 1.705l-3.16 3.08.746 4.349a1 1 0 01-1.45 1.054l-3.906-2.053z" fill="currentColor" fill-rule="evenodd"/></svg></span></span></div></div></label><input type="radio" id="rating-bottom--4" value="5" name="rating-bottom" class="css-i9qcsw"/></div></div><div class="sc-eNPDpu iARtDw"></div></div></div></div></div><div class="sc-eNPDpu iARtDw"></div></div></div><div class="sc-jUpvKA kmRqgF"><footer class="sc-hvvHee APFeF"><div class="sc-eSePXt hbQcmX sc-fvLVrH dUcFyG"><a class="sc-iIHjhz RSHIw" href="https://www.atlassian.com/"><style data-emotion="css 1gskvga">.css-1gskvga{display:inline-block;position:relative;color:var(--logo-color);fill:var(--logo-fill);line-height:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:normal;height:24px;}.css-1gskvga >svg{height:100%;fill:inherit;}.css-1gskvga stop{stop-color:currentColor;}</style><span style="--logo-color:#5E6C84;--logo-fill:#5E6C84" aria-label="Atlassian" role="img" class="css-1gskvga"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198 32" focusable="false" aria-hidden="true" height="32" fill="none"> <path fill=#5E6C84 d="M22.878 24.378 12.293 3.208c-.208-.458-.416-.541-.666-.541-.209 0-.459.083-.709.5-1.5 2.375-2.167 5.125-2.167 8 0 4.001 2.042 7.752 5.043 13.794.333.667.583.792 1.166.792h7.335c.542 0 .833-.208.833-.625 0-.208-.041-.333-.25-.75M7.501 14.377c-.833-1.25-1.083-1.334-1.292-1.334s-.333.083-.708.834L.208 24.46c-.166.334-.208.459-.208.625 0 .334.292.667.917.667h7.46c.5 0 .874-.416 1.083-1.208.25-1 .333-1.876.333-2.917 0-2.917-1.292-5.751-2.292-7.251z"/> <path fill=#5E6C84 d="M107.447 10.828c0 2.972 1.345 5.308 6.795 6.37 3.185.707 3.893 1.203 3.893 2.265 0 1.061-.708 1.698-2.973 1.698-2.619 0-5.733-.92-7.785-2.123v4.813c1.627.778 3.751 1.698 7.785 1.698 5.662 0 7.856-2.548 7.856-6.228m0 .07c0-3.538-1.84-5.166-7.148-6.298-2.902-.637-3.61-1.274-3.61-2.194 0-1.133 1.062-1.628 2.973-1.628 2.335 0 4.6.708 6.794 1.698v-4.6c-1.557-.779-3.892-1.345-6.653-1.345-5.237 0-7.927 2.265-7.927 5.945m72.475-5.803v20.17h4.318V9.979l1.769 4.035 6.087 11.324h5.379V5.166h-4.247v13.022l-1.628-3.821-4.883-9.201zm-27.319 0h-4.671v20.17h4.671zm-10.05 14.154c0-3.538-1.841-5.166-7.149-6.298-2.902-.637-3.609-1.274-3.609-2.194 0-1.133 1.061-1.628 2.972-1.628 2.336 0 4.601.708 6.795 1.699v-4.6c-1.557-.78-3.893-1.346-6.653-1.346-5.238 0-7.927 2.265-7.927 5.946 0 2.972 1.344 5.308 6.794 6.37 3.185.707 3.893 1.203 3.893 2.264 0 1.062-.708 1.699-2.973 1.699-2.618 0-5.733-.92-7.785-2.123v4.812c1.628.779 3.751 1.699 7.785 1.699 5.592 0 7.857-2.548 7.857-6.3M71.069 5.166v20.17h9.625l1.486-4.387h-6.44V5.166zm-19.039 0v4.317h5.167v15.854h4.741V9.483h5.592V5.166zm-6.866 0h-6.157L32 25.336h5.379l.99-3.396c1.204.353 2.478.566 3.752.566s2.548-.213 3.751-.567l.991 3.398h5.379c-.07 0-7.078-20.171-7.078-20.171M42.05 18.259c-.92 0-1.77-.141-2.548-.354L42.05 9.13l2.548 8.776a9.6 9.6 0 0 1-2.548.354zM97.326 5.166H91.17l-7.078 20.17h5.38l.99-3.396c1.203.353 2.477.566 3.751.566s2.548-.213 3.751-.567l.991 3.398h5.379zm-3.114 13.093c-.92 0-1.77-.141-2.548-.354l2.548-8.776 2.548 8.776a9.6 9.6 0 0 1-2.548.354m75.306-13.093h-6.157l-7.007 20.17h5.379l.991-3.396c1.203.353 2.477.566 3.751.566s2.548-.213 3.751-.567l.991 3.398h5.379zm-3.043 13.093c-.92 0-1.77-.141-2.548-.354l2.548-8.776 2.548 8.776a10 10 0 0 1-2.548.354"/> </svg></span></a><nav class="sc-dXfzlN insOyI"><a class="sc-iIHjhz RSHIw" href="/changelog/">Changelog</a><a class="sc-iIHjhz RSHIw" target="_blank" href="https://status.developer.atlassian.com">System status</a><a class="sc-iIHjhz RSHIw" target="_blank" href="https://www.atlassian.com/legal/privacy-policy">Privacy</a><a class="atl-policy-link atl-policy-link-text sc-iIHjhz RSHIw" target="_blank" href="https://www.atlassian.com/legal/privacy-policy#additional-disclosures-for-ca-residents">Notice at Collection</a><a class="sc-iIHjhz RSHIw" target="_blank" href="/platform/marketplace/atlassian-developer-terms/">Developer Terms</a><a class="sc-iIHjhz RSHIw" target="_blank" href="https://www.atlassian.com/legal/trademark">Trademark</a><a class="optanon-toggle-display hide-optanon-link sc-iIHjhz RSHIw">Cookie preferences</a><span class="sc-aewfc fDSCxc">漏 <!-- -->2025<!-- --> Atlassian</span></nav></div></footer></div></div><script nonce="lmXOSVEE5KEQXnUFNg9YWauSt0QbEJTBrFboyZ3cdF8=" type="text/javascript">(function(){var g=function(e,h,f,g){ this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null}; this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "}; this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0}; this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}}; this.start=function(){var t=this;"complete"!==document.readyState?window.addEventListener?window.addEventListener("load",function(){t.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){t.go()}):t.go()};}; try{(new g(100,"r","QSI_S_ZN_basBS9dBHxSA2iN","https://znbasbs9dbhxsa2in-atlassian.siteintercept.qualtrics.com/SIE/?Q_ZID=ZN_basBS9dBHxSA2iN")).start()}catch(i){}})();</script><div id="ZN_basBS9dBHxSA2iN"></div></div></div> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10