JTL Platform
The JTL Platform app connects a JTL-Wawi ERP Cloud tenant to Laioutr. It is a read-only catalog connector: it maps JTL's data onto Laioutr's canonical ecommerce model — through the native JTL ERP GraphQL API — so your frontend can render product listing and search data without knowing the JTL API directly.
@laioutr-app/ui) on top of the canonical data this app supplies.Product). Product detail (images/variations), categories and brands are on the roadmap — see Part 4.Part 1 – Connect JTL and Laioutr (for store owners & project leads)
This section explains which values you need from JTL and where to find them. You can either enter them into the Laioutr project configuration yourself, or hand them to your implementation partner.
1. Information you will need
To connect a JTL tenant to Laioutr you need:
- OAuth2 client credentials (client id + client secret)
- Created when you register a cloud app in the JTL developer portal.
- The secret is used only on the server and is never exposed to the browser. Treat it as a secret and rotate it if it leaks.
- Tenant id
- Identifies which merchant's data the requests read. It is sent as the
X-Tenant-IDheader on every API call. - Without it the API rejects every query with
400 TenantIdMissing.
- Identifies which merchant's data the requests read. It is sent as the
- Permission / scope:
items.read- The app registration must be granted the
items.readpermission so it may query items (products). Missing permission shows up as a403on data queries.
- The app registration must be granted the
- Endpoints (optional)
- Default GraphQL endpoint:
https://api.jtl-cloud.com/erp/v2/graphql. - Default OAuth2 token endpoint:
https://auth.jtl-cloud.com/oauth2/token. - Only override if your tenant is served from a different host.
- Default GraphQL endpoint:
The JTL Platform API is documented at https://developer.jtl-software.com/ (see Using Platform APIs and the GraphQL Schema Reference).
2. Hand the data to your developer or partner
At this point you should have:
- OAuth2 client id and client secret
- the tenant id
- confirmation that
items.readis granted on the app registration - (optional) non-default GraphQL / token endpoints
Developers wire these values into the Laioutr project. No theme or storefront code needs to change inside JTL for the integration itself.
Part 2 – Developer setup in Nuxt
Developers integrate JTL by adding the @laioutr/app-jtl-platform module to the Nuxt app that powers the Laioutr frontend.
Module configuration
All connection values are secret-bearing and live in private runtime config (runtimeConfig['app-jtl-platform']) — never in runtimeConfig.public. This connector exposes no client-visible configuration. Each option also has an environment-variable fallback so secrets can be injected per deployment without rebuilding.
| Option | Env fallback | Required | Description |
|---|---|---|---|
clientId | JTL_CLIENT_ID | yes | OAuth2 client id. |
clientSecret | JTL_CLIENT_SECRET | yes | OAuth2 client secret. Server-only. |
tenantId | JTL_TENANT_ID | yes | Merchant tenant, sent as X-Tenant-ID. |
graphqlUrl | JTL_GRAPHQL_URL | no | GraphQL endpoint. Defaults to https://api.jtl-cloud.com/erp/v2/graphql. |
tokenUrl | JTL_TOKEN_URL | no | OAuth2 token endpoint. Defaults to https://auth.jtl-cloud.com/oauth2/token. |
scope | JTL_SCOPE | no | Optional OAuth2 scope. |
When no credentials are configured, the connector serves built-in fixtures so a storefront/playground still renders products end-to-end. Configure real credentials to switch to live data.
Project config (laioutrrc.json)
Add the connector to the apps array of the project's laioutrrc.json:
{
"apps": [
{
"name": "@laioutr/app-jtl-platform",
"version": "latest",
"config": {
"clientId": "your-oauth-client-id",
"clientSecret": "your-oauth-client-secret",
"tenantId": "your-tenant-id"
}
}
]
}
laioutrrc.json carries project secrets and is not committed to version control. In production the Laioutr platform supplies it; for local development you can also provide the secrets via the JTL_* environment variables (see .env.example in the repository).
Runtime behavior (high level)
- Single-tenant per deployment. One configured client serves all requests; there is no per-request, per-tenant credential injection.
- OAuth2 client-credentials. The connector obtains a Bearer token from the token endpoint, caches it and renews it ~60 s before expiry (tokens last ~24 h). On a
401it refreshes the token once and retries. - Request-scoped client. The orchestr middleware builds one authenticated JTL client per request and exposes it to every handler, alongside the resolved
localeandcurrencyfrom the per-request client environment. - Resilient transport. Every request carries
Authorization: Bearer …andX-Tenant-ID. GraphQL errors are read from the response body (a200 OKcan still carry errors);429/5xxresponses are retried with exponential backoff and jitter.
Part 3 – What the JTL integration provides (for developers)
Once configured, the @laioutr/app-jtl-platform package implements the relevant parts of Laioutr's canonical ecommerce model through the orchestr. Your frontend talks to the canonical model, not to JTL directly.
Built-in capabilities
- Canonical queries
- Product — product listing and full-text search (backed by the JTL
QueryItemsGraphQL query:searchTerm+ cursor pagination).
- Product — product listing and full-text search (backed by the JTL
- Resolvers (hydrate canonical components)
- Product component resolver, mapping each JTL item onto
ProductBase(name + derived slug),ProductDescription,ProductInfo(short description, brand),ProductBrand(manufacturer) andProductPrices(gross price).
- Product component resolver, mapping each JTL item onto
- Connectivity endpoints (for setup/verification)
GET /api/jtl-health— runs the OAuth + GraphQL round-trip;200when live,503otherwise.GET /api/jtl-items?q=&limit=&offset=— listing/search probe returning raw JTL items (live when configured, fixtures otherwise).
- GraphQL types
- Generated from the committed JTL ERP SDL (
schema.graphql) viagraphql-codegen(pnpm codegen) — works offline, no credentials required.
- Generated from the committed JTL ERP SDL (
For exact type names and payloads, check the package source and the @laioutr-core canonical type definitions.
Part 4 – Extending the integration
You can extend the JTL integration while staying within Laioutr's orchestr and canonical model.
1. Product detail (PDP)
- Add a
GetItemByIdGraphQL operation and mapItemdetailsItemonto the remaining canonical components: images (ItemImages.defaultImageUrl→ProductMedia), variations (ProductDefaultVariant), the realurlPathslug and SEO (metaDescription).
2. Categories, navigation and brands
- Map
QueryCategories(flat list +parentId→ tree) onto canonical Category/Menu, andQueryManufacturersonto brands. Register query template providers so Studio editors can wire them visually.
3. Listing depth & performance
- Switch the offset-bridged listing to true cursor pagination (carry
pageInfo.endCursor), and add a batch-by-id fetch (where: { id: { in } }) for cache-restore paths. Query only the fields your UI renders.
4. Custom sections and blocks for Studio
- Build sections/blocks that consume the canonical queries — and keep them backend-agnostic (depend only on canonical types, never on JTL-specific payloads), so your UI stays portable if you add or switch commerce backends later.
Reference
The integration follows the JTL developer guides:
Changelog
All changelogs are managed in CHANGELOG.md in the package's GitHub repository (laioutr/app-jtl-platform). Use that repo's CHANGELOG.md for release notes.
Hygraph
Laioutr app package that connects a Nuxt storefront to Hygraph's Content API, Orchestr, Studio media, and Nuxt Image, using a sample content model as a starting point only.
Nimstrata Google Retail API
Developer documentation for the Laioutr Nimstrata app package. Add AI-powered search, recommendations, suggested search, and event tracking to your Laioutr frontend via the Nimstrata (Retail Connect) API, with Shopify integration.