How to integrate your app with the JTL App Shell using the manifest and AppBridge communication
This guide covers the two systems that control how your Cloud App renders and communicates inside the JTL platform:
Manifest: JSON configuration that tells JTL where to load your app, what capabilities it has, and what permissions it needs.
AppBridge: Runtime SDK that enables bidirectional communication between your app (in an iframe) and the host environment (JTL Hub or ERP).
It also covers the Platform UI component library for building interfaces that match JTL’s design system.For authentication flows, see Authentication & Login. For calling the JTL Cloud and JTL-Wawi APIs, see Using Platform APIs.
The manifest is a JSON file that defines your app’s identity, lifecycle hooks, and capabilities. You provide it when registering your app in the Partner Portal.
Define translations for your app’s name, description, and any other user-facing text. JTL selects the correct locale based on the merchant’s language preference.
Property
Type
Description
defaultLocale
string
Default locale code in ISO format (e.g., de-DE)
locales
object
Maps locale codes to translation key-value pairs
Template variables like __TK_key1__ in name and description fields are replaced with values from the matching locale at runtime.
The lifecycle object defines URLs that JTL calls during app installation and removal:
Property
Type
Description
lifecycle.setupUrl
string
URL loaded in an iframe during installation. Use this to display a login or onboarding screen and link the merchant’s tenant to your app.
lifecycle.connectUrl
string
Webhook URL called when the app is installed.
lifecycle.disconnectUrl
string
Webhook URL called when the app is uninstalled.
A working example of the setup flow is in the sample app’sSetupPage.tsx at src/hello-world-app/packages/frontend/src/setupPage/SetupPage.tsx and the corresponding /connect-tenant route in src/hello-world-app/packages/backend/src/index.ts.
Specify the minimum Cloud API version your app is compatible with. JTL uses this to prevent installations on environments that don’t meet the requirement.
Capabilities define where and how your app integrates with JTL. Each key maps to a specific integration surface. See Architecture Overview for a full description of each integration type.
Add custom tabs to specific ERP views like product detail or customer detail. Each tab loads your app’s URL in context, with access to features scoped to that view.
Property
Type
Description
context
string
Where the tab appears (e.g., productDetail, customerDetail)
name
string
Display name shown on the tab
url
string
Content URL loaded when the tab is selected
features
array
Permission features needed for the tab to function
Add sidebar panels that appear alongside ERP views. Panes are context-aware: they show up on specific pages and can react to what the merchant is viewing.
Property
Type
Description
url
string
URL loaded in the pane iframe
title
string
Title shown in the pane header
context
string
Dot-notation path where the pane appears (e.g., $tenantSlug.customers)
matchChildContext
boolean
Flag that determines whether or not the whole context needs to match for the App to be displayed
requiredScopes
array
(optional) Granular API permission specific to the pane
The AppBridge is provided by the @jtl-software/cloud-apps-core package. It establishes a secure communication channel between your app’s frontend (running in an iframe) and the host JTL environment (JTL Hub or ERP Cloud).The bridge allows your app to request data (like session tokens), call host methods, and expose functions to the host. Publish/subscribe event handling is in development (see below).
Initialize the AppBridge before rendering your React app, then pass the instance as a prop or store it in context:
import { createAppBridge } from '@jtl-software/cloud-apps-core';import { createRoot } from 'react-dom/client';createAppBridge().then((appBridge) => { createRoot(document.getElementById('root')!).render( <StrictMode> <App appBridge={appBridge} /> </StrictMode>, );});
What this does: Calls createAppBridge() to establish the iframe-to-host connection, waits for the bridge to be ready, then passes it to your app as a prop. This guarantees the communication channel is open before any component tries to use it.
Do not initialize the AppBridge inside a component (e.g., in useEffect). This can cause race conditions where components render before the bridge is ready. Always initialize it at the application entry point.
For Next.js apps that need SSR compatibility, use a dynamic import inside a client-side provider instead. See the From Scratch quickstart for the full pattern.
You can use AppBridge in any JavaScript frontend framework, including React,
Vue, and Angular.
The AppBridge creates a two-way channel: your app’s appBridge instance communicates with a corresponding hostAppBridge instance inside the JTL Cloud service.All communication is asynchronous and non-blocking. Your app continues executing while messages are delivered between the iframe and the host. There are no HTTP requests or polling involved.
What this does: Registers a function that the host (JTL) can call by name. This is how the host accesses logic implemented in your app (e.g., custom calculations, data lookups).
In development: AppBridge publish/subscribe events are in development and not yet available. This section will be updated when the API ships.
AppBridge events will provide two capabilities:
event.subscribe: listen for events emitted by the host (for example, inventory:updated when a merchant changes stock elsewhere in the ERP).
event.publish: send events to the host so it can react to actions your app completes (for example, order:verification:complete).
Topics will follow a resource:action naming convention so intent is clear from the name alone. Payloads will be small by design (IDs and changed values), not full objects.
JTL exposes different built-in methods depending on which environment your app is running in.
Setup Environment (JTL Hub)
ERP Environment (ERP Cloud)
These methods are available when your app loads via the lifecycle.setupUrl during installation:
Method
Parameters
Returns
Description
getSessionToken
None
Promise<string>
Returns the current session token (contains user and tenant info)
setupCompleted
None
Promise<void>
Signals that setup is done and activates the app in the Hub
These methods are available when your app runs inside the ERP (via menu items, tabs, or panes):
Method
Parameters
Returns
Description
getSessionToken
None
Promise<string>
Returns the current session token
getCurrentTime
None
Promise<Date>
Returns the current time as a Date object
getSessionToken is available in both environments. It’s the primary way your frontend identifies the current user and tenant. For details on verifying session tokens on your backend, see Authentication & Login.
JTL provides a React component library that matches the platform’s design system. Using these components ensures your app looks and feels consistent with the rest of the JTL interface.