A app manifest is a JSON-formatted configuration that defines a app's properties, behavior, and capabilities within the system. This document outlines the structure and elements of the manifest.
Property | Type | Description |
---|---|---|
manifestVersion | string | Specifies the version of the manifest schema (format: "major.minor.patch") |
version | string | The version of the app itself (format: "major.minor.patch") |
Accepts a short and full property, both are simple strings. The full property serves as the Display-name of a given app, whereas the short property describes an identifier.
Property | Type | Description |
---|---|---|
short | string | Brief name of the app (supports template keys like __TK_key1__ ) |
full | string | Complete name of the app |
The description
object provides information about the purpose and functionality of the app:
Property | Type | Description |
---|---|---|
short | string | Brief summary of the app (50-150 characters recommended) |
full | string | Detailed description explaining the app's features and benefits (150-1000 characters recommended) |
Both properties support template keys using the __TK_key1__
syntax for localization.
The defaultLocale
takes the descriptor of the app's default language setting as a string that has to match one of the descriptors in the locales
object.
the locales
describes the languages the App supports by providing a descriptor and an object of key-value pairs. Keys being the variables used in the code and values being their respective displayed texts in the app. As in the name.short example above, a specified variable can be used using the following syntax:
Property | Type | Description |
---|---|---|
defaultLocale | string | Default locale code (ISO format, e.g., "de-DE") |
locales | object | Maps locale codes to translation key-value pairs |
Accepts a dark and light property as links to where the App Icon is stored. The chosen image will be displayed in the app card in the hub. depending on the theme either the dark or light variants will automatically be chosen. Should the image not be available, it will be displayed as a placeholder.
Property | Type | Description |
---|---|---|
light | string | Icon URL for light themes (HTTPS URL, PNG/SVG recommended) |
dark | string | Icon URL for dark themes (HTTPS URL, PNG/SVG recommended) |
The communication
object contains resources for users to get help and learn about the app:
Property | Type | Description |
---|---|---|
supportUrl | string | URL where users can get technical help or report issues with the app. Supports the __ACTIVE_LOCALE__ template variable for localization. |
guideUrl | string | URL to comprehensive documentation that explains how to use the app's features. Supports the __ACTIVE_LOCALE__ template variable for localization. |
The legal
object contains URLs for compliance and legal documentation:
Property | Type | Description |
---|---|---|
gdprRequestUrl | string | URL for users to submit GDPR data access requests, allowing them to view what personal data is stored |
gdprDeleteUrl | string | URL for users to submit GDPR data deletion requests when they want their personal data removed |
privacyUrl | string | URL to the app's privacy policy, which outlines how user data is collected, used, and protected |
termsOfUseUrl | string | URL to the terms of service document that defines the conditions under which users may access and use the app |
The lifecycle
object defines integration points for the app's installation process:
Property | Type | Description |
---|---|---|
setupUrl | string | URL called during app installation that can display a login screen to match the app's user/tenant with the installing cloud tenant |
connectUrl | string | Webhook URL that will be triggered when the app is installed (functionality not yet implemented) |
disconnectUrl | string | Webhook URL that will be triggered when the app is uninstalled (functionality not yet implemented) |
A working example of this can be found in the Example app's SetupPage.tsx located at: '/examples/hello-world-app/frontend/src/setupPage/SetupPage.tsx' as well as the corresponding "/connect-tenant" route found in "/examples/hello-world-app/backend/src/index.ts"
The requirements
object contains:
Property | Type | Description |
---|---|---|
minCloudApiVersion | string | Minimum compatible API version |
The capabilities.hub
object defines how the app integrates with the JTL-Hub:
Property | Type | Description |
---|---|---|
appLauncher.redirectUrl | string | URL that the system redirects to when the app's card is clicked in the hub |
The capabilities.pane
object defines how the app integrates with the pane sidebar of the JTL-ERP:
Property | Type | Description |
---|---|---|
url | string | Desired URL to show in the pane view |
title | string | Title of your app shown in the pane view |
context | string | Dot notation of the url path you want your app to be available in |
matchChildContext | boolean | Flag that determines whether or not the whole context needs to match for the App to be displayed |
The capabilities.erp
object defines how the app integrates with the JTL-ERP:
Property | Type | Description |
---|---|---|
headless.url | string | URL for headless mode (TBD) |
The menuItems
array defines custom navigation elements in the ERP interface:
Property | Type | Description |
---|---|---|
id | string | Internal identifier for the menu item |
name | string | Display name shown in the navigation |
url | string | (optional) Link to the content when the item is clicked |
children | array | (optional) Nested sub-menu items with the same structure |
Menu items can be nested using the children
property, creating hierarchical navigation. Currently, only root items are supported in the implementation, so nested children won't affect the app's behavior.
Each item in the tabs
array defines a custom tab that appears in specific contexts:
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 |
The api
object contains:
Property | Type | Description |
---|---|---|
scopes | array | API permission scopes required |
The manifest supports these template variables:
__TK_key1__
: Replaced with translation values from thelocales
section__ACTIVE_LOCALE__
: Replaced with the user's active locale
{
"manifestVersion": "1.0.0",
"version": "1.0.0",
"name": {
"short": "Hello World example",
"full": "Hello World example"
},
"description": {
"short": "Official Hello World example.",
"full": "This is the official Hello World example."
},
"defaultLocale": "de-DE",
"locales": {
"de-DE": {
"key1": "abc"
},
"en": {
"key1": "abc"
}
},
"icon": {
"light": "https://hub.jtl-cloud.com/assets/image-placeholder.png",
"dark": "https://hub.jtl-cloud.com/assets/image-placeholder.png"
},
"communication": {
"supportUrl": "https://example.com/support-for-plugin-xy/__ACTIVE_LOCALE__/",
"guideUrl": "https://example.com/guide-for-plugin-xy?lang=__ACTIVE_LOCALE__"
},
"legal": {
"gdprRequestUrl": "https://example.com/gdpr/request",
"gdprDeleteUrl": "https://example.com/gdpr/delete",
"privacyUrl": "https://example.com/privacy",
"termsOfUseUrl": "https://example.com/terms-of-use"
},
"lifecycle": {
"setupUrl": "http://localhost:50142/setup",
"connectUrl": "https://jtl.integrations.example.com/lifecycle/connect",
"disconnectUrl": "https://jtl.integrations.example.com/lifecycle/disconnect"
},
"capabilities": {
"hub": {
"appLauncher": {
"redirectUrl": "http://localhost:50142/erp"
}
},
"erp": {
"headless": {
"url": "https://jtl.integrations.example.com/erp"
},
"menuItems": [
{
"id": "<MENU ITEM ID>",
"name": "<MENU ITEM NAME>",
"url": "http://localhost:50142/erp"
}
],
"pane": [
{
"url": "http://localhost:50142/pane",
"title": "Test Pane",
"context": "customers",
"matchChildContext": true
}
]
}
}
}