Developer
News and Updates
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Last updated Feb 26, 2026

Redirecting URLs from Connect to Forge

Forge supports URL persistence for Connect page module URLs. This capability allows your app to use a platform-level bridge that keeps your Connect app's existing URLs working when migrating it to Forge. For Jira and Confluence apps that rely on permanent URLs, Forge will accept the original Connect URL (including its full path, query parameters, and fragments) and transparently redirect it to the corresponding Forge app module.

This page describes how to preserve a Connect app's page module URLs when migrating it to Forge, ensuring that customer bookmarks and shared links continue to work.

URL persistence is primarily intended for enabling backward compatibility with Connect apps. Avoid relying on it to provide new Forge features.

Limitations

Forge doesn't support URL persistence for app modules created via Dynamic Modules.

In addition, URL persistence has the following known limitations:

How it works

Forge performs matching via module ID: {addonKey}__{moduleKey}. Jira/Confluence finds the Forge app whose app.connect.key in the manifest file matches the Connect app key, then finds the Forge module whose key matches the obsolete Connect module key.

Afterwards, Forge will build the resulting URL based on the corresponding module type. This URL uses some or all of the following variables:

VariableDescription
{baseUrl}The app host URL
{appKey}The app key (equal to connect.app.key in the Forge manifest)
{moduleKey}The module key
{projectKey}The project or space key
{projectType}The type of project, such as core, software, servicedesk, etc.
{appId}The Forge app ID
{envId}The Forge environment ID
{route}The string declared in the Forge module properties

Supported Connect module sources

For these supported modules, Jira and Confluence will extract the app key and module key from the source URL:

Connect module typesURL format
General Page (for Jira or Confluence ) {baseUrl}/plugins/servlet/ac/{appKey}/{moduleKey}
Jira Project page {baseUrl}/projects/{projectType}/{projectKey}?selectedItem=com.atlassian.plugins.atlassian-connect-plugin:{appKey}__{moduleKey}

Supported Forge target module types

For Forge module targets, use the following URL formats:

Forge module typesURL format
jira:globalPage{baseUrl}/jira/apps/{appId}/{envId}
jira:adminPage{baseUrl}/jira/settings/apps/get-started/{appId}/{envId}
jira:personalSettingsPage{baseUrl}/jira/settings/personal/apps/{appId}/{envId}
jira:projectPage{baseUrl}/jira/{projectType}/projects/{projectKey}/apps/{appId}/{envId}
jira:projectSettingsPage{baseUrl}/jira/{projectType}/projects/{projectKey}/settings/apps/{appId}/{envId}
jiraServiceManagement:queuePage{baseUrl}/jira/servicedesk/projects/{projectKey}/queues/apps/{appId}/{envId}
confluence:globalPage{baseUrl}/apps/{appId}/{envId}/{route}
confluence:globalSettings{baseUrl}/admin/forge/apps/{appId}/{envId}/{moduleKey}

Supported redirects

Depending on the source URL formats, additional parameters may be required to determine the destination URL:

Forge module typesFrom Connect General PageFrom Connect Project Page
jira:globalPageYesYes
jira:adminPageYesYes
jira:personalSettingsPageYesYes
jira:projectPageYes, but only if the URL includes a valid project.id query parameter.Yes
jira:projectSettingsPageYes, but only if the URL includes a valid project.id query parameter.Yes
jiraServiceManagement:queuePageYes, but only if the URL includes a valid project.id query parameter.Yes
confluence:globalPageYesN/A
confluence:globalSettingsYesN/A

For jiraServiceManagement:queuePage, the resulting page will not load as expected if the supplied project is not for Jira Service Management, even if the redirection process is completed.

How to implement

To implement URL persistence from Connect to Forge:

  1. Create matching Forge modules in the manifest. The module ID {addonKey}__{moduleKey} should be identical on both Forge and Connect apps so they can be matched. For each Connect URL you want to preserve (for example, generalPages), ensure that:

    • The app.connect.key matches the source Connect app's key.
    • Each URL's Connect module should have a matching Forge module with an identical key. See the following example.
  2. Handle the x_atlassian_cf parameter in Forge. On the Forge app page, read and decode the x_atlassian_cf query parameter. For example:

    1
    2
    import { useEffect } from 'react';
    import { view } from "@forge/bridge";
    import ForgeReconciler from  '@forge/react';
    
    const extractConnectUrl = (location) => {
      const { search } = location || {};
      if (!search) {
        return null;
      }
      try {
        const params = new URLSearchParams(search);
        const base64encodedUrl = params.get("x_atlassian_cf");
        return base64encodedUrl ? atob(base64encodedUrl) : null;
      } catch (e) {
        console.warn("Failed to extract the Connect URL.", { location }, e);
        return null;
      }
    };
    
    const handleConnectUrl = async () => {
      try {
        const { location } = await view.createHistory();
        const connectUrl = extractConnectUrl(location);
        console.log("handleConnectUrl", {
          location,
          connectUrl,
        });
        // Provide a backward-compatible experience using the original URL.
        if (connectUrl) {
            // ...
        }
      } catch (e) {
        console.error("Failed to retrieve the Connect URL", e);
      }
    };
    
    const App = () => {
      useEffect(() => {
        handleConnectUrl();
        return () => {
          // ... cleanup, etc.
        };
      }, []);
    };
    
    ForgeReconciler.render(
        <React.StrictMode>
            <App />
        </React.StrictMode>
    );
    

    This example uses the original Connect URL inside the query parameter x_atlassian_cf (including the path, query string, and fragment). This helps preserve consistent behaviour, such as routing to the proper view in your app.

The payload value of the query parameter x_atlassian_cf in the Forge URL is a Base64-encoded variant of the original Connect URL. While the URL persistence feature itself doesn’t have a length limit for the original Connect URL, the Atlassian platform does. The entire URL must contain no more than 8192 characters.

Example manifest changes

This example shows what changes to a Connect and Forge module should look like in a Connect-to-Forge app.

Connect module

Remove the original Connect module declaration:

1
2
connectModules:
  jira:generalPages:
    - key: hello-world-global-page
      location: system.top.navigation.bar
      name:
        value: Hello World!
      url: /hello-world

Forge replacement

Then, add the new Forge module declaration:

1
2
modules:
  jira:globalPage:
    - key: hello-world-global-page
      resource: main
      resolver:
        function: resolver
      render: native
      title: Hello World!

Example behaviour

With URL persistence implemented, a customer could have a bookmark to a Connect module URL like the following:

https://example.atlassian.net/plugins/servlet/ac/com.example.app/connect-module-key-1?var1=&var2=%F0%9F%90%90#!welcome/asset?id=1001

Whenever they access this bookmark, Jira or Confluence will redirect it to the corresponding Forge page module's URL, for example:

https://example.atlassian.net/jira/apps/00000000-0000-0000-0000-000000000000/ffffffff-ffff-ffff-ffff-ffffffffffff?x_atlassian_cf=aHR0cHM6Ly9leGFtcGxlLmF0bGFzc2lhbi5uZXQvcGx1Z2luL3NlcnZsZXQvYWMvY29tLmV4YW1wbGUuYXBwL2Nvbm5lY3QtbW9kdWxlLWtleS0xP3ZhcjE9JnZhcjI9JUYwJTlGJTkwJTkwIyF3ZWxjb21lL2Fzc2V0P2lkPTEwMDE%3D

Where:

  • com.example.app is its Connect app key
  • connect-module-key-1 is the Connect module key for the obsolete module
  • 00000000-0000-0000-0000-000000000000 is the Forge app ID
  • ffffffff-ffff-ffff-ffff-ffffffffffff is the Forge environment ID

Rate this page: