Skip to main content
This guide outlines the essential patterns for building production-ready Cloud Apps. Each section focuses on a specific part of your app’s architecture, with practical guidance and code examples where relevant.

AppBridge Initialization

How you initialize the AppBridge determines whether your app starts reliably or fails intermittently with race conditions.

Initialize Before Rendering

Always create the AppBridge instance before your React app renders. If you initialize it inside a component (e.g., in useEffect), child components may try to access the bridge before it’s ready.

Use Dynamic Imports for SSR Frameworks

If you’re using Next.js or another framework with server-side rendering, the AppBridge SDK fails on the server because it requires a browser environment. Use a client-side provider with dynamic imports.
What this does: Delays the import until the component runs in the browser, preventing window is not defined errors during server rendering. See the From Scratch quickstart for the full provider pattern.

Handle Initialization Failures

The AppBridge can fail to initialize if your app isn’t running inside the App Shell (e.g., during local development in a regular browser tab). Always catch errors and display a helpful message.

Authentication

Token management is the most common source of production issues. These patterns prevent the majority of auth-related failures.

Cache Access Tokens

Access tokens are valid for approximately 24 hours. Requesting a new token on every API call wastes time and puts unnecessary load on the auth server. Cache the token in memory and refresh it before expiry.
What this does: Reuses the cached token until 60 seconds before expiry, then fetches a fresh one. The buffer prevents failures from tokens expiring mid-request.

Retry on 401

Even with caching, tokens can expire unexpectedly (server clock drift, cache invalidation). Retry once with a fresh token before surfacing the error.

Never Expose Credentials to the Frontend

Your CLIENT_SECRET must stay on the server. Never include it in frontend code, environment variables prefixed with NEXT_PUBLIC_, or client-side bundles. The frontend authenticates through the AppBridge session token, not client credentials.

Refresh Session Tokens before Sensitive Operations

Session tokens from the AppBridge are short-lived. Request a fresh one before operations that require verified identity, rather than reusing a token obtained minutes ago.

API Usage

Efficient API usage keeps your app fast and prevents rate limiting.

Request Only the Fields You Need

GraphQL lets you specify exactly which fields to return. Avoid requesting fields your UI doesn’t display. Smaller payloads mean faster responses and less bandwidth.

Paginate Large Datasets

Never fetch all records at once. Use cursor-based pagination with a reasonable page size (10-50 items). Fetch the next page only when the user scrolls or clicks “Load more.”
What this does: Fetches items in pages of 50 until all records are retrieved. For background sync jobs this is fine, but for UI-driven fetching, load pages on demand instead of fetching everything upfront.

Handle GraphQL Errors in the Response Body

GraphQL returns errors inside the JSON body, not as HTTP status codes. A 200 OK response can still contain errors. Always check both data and errors.

Error Handling

Consistent error handling prevents your app from crashing and gives merchants useful feedback when things go wrong.

Wrap API Calls in try/catch

Every API call can fail. Network issues, expired tokens, rate limits, and server errors all produce exceptions. Catch them and provide meaningful error states.

Distinguish Error Types

Different errors require different responses. A network timeout should be retried. A 403 should prompt the merchant to check permissions. A validation error should highlight the problematic field.

Show Loading and Error States

Never leave the merchant looking at a blank screen. Show a loading indicator while data is being fetched, and a clear error message if something fails.

Security

These practices protect both your app and the merchants who use it.

Verify Session Tokens on the Backend

Never trust a session token without verifying it. The frontend can be manipulated. Your backend should verify every session token against JTL’s JWKS before using the tenant ID from it.

Validate Tenant ID on Every Request

When your frontend sends a tenant ID to your backend, verify it matches the tenant ID in the verified session token. This prevents one merchant from accessing another merchant’s data.

Use HTTPS in Production

All production URLs in your manifest (configurationUrl, menu item URLs, panel URLs) must use HTTPS. HTTP is acceptable for localhost during development only.

Store Credentials Securely

Keep your CLIENT_SECRET in environment variables. Never commit .env files to version control. Use a secrets manager (AWS Secrets Manager, Vault, Doppler) for production deployments.

Performance

Fast apps get more installs and fewer support tickets.

Cache JWKS Responses

JTL’s public keys change infrequently. Fetching them on every session token verification adds latency. Cache the JWKS response and refresh it only when verification fails with a key mismatch.
What this does: Caches the JWKS for one hour and reuses it across all session token verifications. If a token fails verification, you can clear the cache and retry with fresh keys before returning an error.

Minimize Frontend Bundle Size

Use dynamic imports for the AppBridge SDK and any heavy dependencies. This reduces your initial page load, which matters because your app loads inside an iframe that already has the full ERP UI rendered around it.

Deployment Checklist

Before submitting your app to the App Store, verify each item on this list.
1

Update manifest URLs

Replace all localhost URLs in your manifest with production HTTPS URLs. This includes configurationUrl, redirectUrl, menu item URLs, and panel URLs.
2

Verify credentials

Confirm your CLIENT_ID and CLIENT_SECRET are set in your production environment. Test the token exchange from your deployed server.
3

Test the full install flow

Walk through the complete flow before deploying: install from JTL Cloud, complete setup, verify data loads, test all features, then uninstall and confirm cleanup.
4

Review error handling

Confirm your app handles token expiry, network failures, and empty data states without crashing or showing blank screens.
5

Validate icon URLs

Make sure your manifest’s icon.light and icon.dark point to publicly accessible HTTPS URLs, not local paths.
6

Test uninstall/reinstall

Uninstall your app and reinstall it. Verify that the setup flow works correctly a second time and any previously saved data is handled gracefully.

What’s Next

Submit to the App Store

Deploy your app and publish it for merchants.

Architecture Overview

Review the full architecture of JTL Cloud Apps.

Error Handling

In-depth error format reference and retry strategies.