Svelte Commerce × Broadleaf
Svelte Commerce on Broadleaf
The Broadleaf connector targets Broadleaf Microservices — 41 OpenAPI 3.0.3 documents — not the legacy 5.x/6.x monolith, which publishes no versioned REST contract. Cart, checkout and sign-in are wired, and CONNECTORS.md records no gaps.
- 28/43 services wired
- @misiki/broadleaf-connector 0.5.0
- Cart wired
- Checkout wired
- Sign-in (auth) wired
What works on Broadleaf today
Cart, checkout and sign-in are wired, with no gaps recorded. One question is open with Broadleaf: its published CartPricing schema has no cart total, though its demo gateway returns one, so a deployment that follows the spec to the letter would show a total of zero.
Cart
Wired: issues a real request to Broadleaf.
Checkout
Wired: issues a real request to Broadleaf.
Sign-in (auth)
Wired: issues a real request to Broadleaf.
Known gaps: none recorded.
28 of 43 services wired, read from CONNECTORS.md on ; npm may carry a newer patch. How coverage is measured.
What the connector calls on Broadleaf
The connector calls the REST services of Broadleaf Microservices through one gateway, with no single base path: each service has its own context path, such as /api/catalog-browse, /api/cart-operations, /api/order-operations, /api/customer and /api/payment, and sign-in goes to /auth, which is not under /api.
A shopper signs in with POST /auth/embedded/login (form-encoded username and password), which returns a one-time passcode that the connector exchanges at POST /auth/oauth/token (grant_type=authorization_code, purpose=OTP) for a bearer JWT and refresh token, held in the connector’s shared credentials; the BLCART and BLSID cookies Broadleaf sets are captured and sent back as a Cookie header during server rendering.
| Service | What it requests |
|---|---|
product | GET /api/catalog-browse/search/catalog with query, page, size and sort, sent without a token; GET /api/catalog-browse/products/details with productUris, then productIds |
category | GET /api/catalog-browse/categories/details with categoryId or categoryUrl and hydrateProducts=false; GET /api/catalog/categories and /api/catalog/categories/subcategories with a client-credentials token |
search | GET /api/catalog-browse/search/catalog with filters[n].name, filters[n].values and filters[n].ranges[0].minValue/maxValue; GET /api/catalog-browse/search/catalog/suggest for type-ahead |
cart | POST /api/cart-operations/cart with the first item, GET /cart/{cartId}, POST /cart/{cartId}/items, PATCH or DELETE /cart/{cartId}/items/{cartItemId}, POST /cart/{cartId}/pricing, POST and DELETE /cart/{cartId}/offer-codes, and GET /resolve-cart for a signed-in shopper |
checkout | POST /api/cart-operations/checkout/{cartId}/guest-token, contact-info, GET /checkout/{cartId}/fulfillment-options, POST /fulfillment-options/{cartId}/select, GET /checkout/{cartId}/payment-method-options, POST /api/payment/payments, then POST /checkout/{cartId}/process |
order | GET /api/order-operations/order-history with offset, size and sort=submitDate,desc, GET /order-history/{orderNumber}, and GET /api/cart-operations/cart-history as a fallback |
auth | POST /auth/embedded/login, POST /auth/oauth/token, GET /auth/me, POST /auth/register/embedded/submit, POST /auth/embedded/request-password-reset and GET /auth/logout, each with client_id |
address | GET, POST, PUT and DELETE on /api/customer/customers/{customerId}/addresses, where the customer ID is the serviceId from GET /auth/me |
Broadleaf rules the connector follows
- Every call carries an
X-Context-Requestheader, a JSON object withtenantIdandapplicationId; without it Broadleaf’s catalogue search answers 400INVALID_SEARCH_REQUEST. - Every cart write sends
X-Cart-Versionwith theversionfrom the last cart the connector read, because Broadleaf locks carts optimistically and answers 400CART_VERSION_REQUIREDwithout it; the connector reads the cart first when it has not yet seen a version. - The
/checkout/*routes answer 401 to an anonymous caller, so for a shopper who is not signed in the connector first requests anX-Guest-TokenfromPOST /checkout/{cartId}/guest-tokenand sends it on each checkout call. - Broadleaf pages are numbered from 0 and only the numbered envelope carries
totalElementsandtotalPages; the offset envelope used for categories, addresses and order history publishes no totals, so the connector reports them as 0 rather than counting the rows it received. - There is no route per payment provider: the connector reads the enabled
paymentMethodGatewayTypevalues frompayment-method-options, creates a payment withownerType: 'BLC_CART', and throwsNotSupportedErrorwhen the store has no matching gateway rather than guessing a path.
Read from the source of misiki-in/broadleaf-connector at commit 729560e of . Where the code has changed since, the code is right.
Quick start
From nothing to a Svelte Commerce storefront reading Broadleaf. You need Node.js and a Broadleaf to point it at; the storefront holds no data of its own.
Clone it, choose the connector, point it at Broadleaf
# 1 — get the storefront
git clone https://github.com/itswadesh/svelte-commerce
cd svelte-commerce
# 2 — one connector at a time: remove the two the storefront ships with, add this one
npm uninstall @misiki/litekart-connector @misiki/vendure-connector
npm i @misiki/broadleaf-connector
# 3 — point it at your Broadleaf gateway
echo PUBLIC_BROADLEAF_API_URL=https://your-store.example.com >> .env
# 4 — run it
npm run dev Switching works the same way on every backend: what all 26 share, from one connector at a time to store identity.
Environment variables
| Variable | Required | What it does |
|---|---|---|
PUBLIC_BROADLEAF_API_URL | Yes | Base URL of your Broadleaf Microservices gateway. Boot fails, naming this variable, if it is missing. |
PUBLIC_BROADLEAF_API_KEY | No | OAuth client ID. With the secret, the connector requests a client-credentials token, which menu, customer and ratings calls need; catalogue browsing does not. |
PUBLIC_BROADLEAF_API_SECRET | No | OAuth client secret, sent with the ID as HTTP Basic to /oauth/token. See the limitations before setting it. |
PUBLIC_BROADLEAF_ACCESS_TOKEN | No | A bearer token to use instead; when one is set, the connector skips the client-credentials request. |
PUBLIC_BROADLEAF_STORE_ID | No | Sent as Broadleaf’s applicationId. |
PUBLIC_BROADLEAF_CHANNEL_ID | No | Sent as Broadleaf’s tenantId. |
PUBLIC_CONNECTOR | No | Only when more than one connector is installed: @misiki/broadleaf-connector names the one this build runs on. |
init.ts hands the connector every PUBLIC_BROADLEAF_* variable that is set, camel-cased: PUBLIC_BROADLEAF_STORE_ID arrives as storeId. The guide also lists PUBLIC_BROADLEAF_ACCESS_KEY; the connector’s source does not read it.
Every variable here begins PUBLIC_, and SvelteKit sends PUBLIC_ variables to the browser: treat each value you set as published.
What to set up on Broadleaf
- Run Broadleaf Microservices. The connector is wired against its OpenAPI documents; the 5.x/6.x monolith publishes no versioned REST contract to wire against.
- Create an OAuth client for the storefront if you want menus, customer and ratings calls: they need an application token, while catalogue browsing is anonymous.
How the integration works
The connector speaks Broadleaf Microservices’ REST APIs, as described by 41 OpenAPI 3.0.3 documents, and not the 5.x/6.x monolith. It takes a client-credentials token when it has an OAuth client ID and secret, and sends tenantId and applicationId from the channel and store variables.
Limitations on Broadleaf
- No gaps are recorded for Broadleaf in CONNECTORS.md.
- An open question on cart totals: Broadleaf’s published
CartPricingschema has nototal,adjustmentsTotalorfeesTotal, but the demo gateway returns them. A deployment that follows the spec strictly would render a cart total of zero. - If you set
PUBLIC_BROADLEAF_API_SECRET, the OAuth client secret reaches every visitor: SvelteKit sendsPUBLIC_variables to the browser.
Before you rely on it
No connector has been exercised against a live production instance of its platform; each was written from the platform’s published source. The limits every backend shares and the errors every switch can meet are on the backends page.
An open question for Broadleaf’s maintainers: CartPricing in the published schema has no total, adjustmentsTotal or feesTotal, but the demo gateway returns them. Which is authoritative?
FAQ
Questions about Svelte Commerce on Broadleaf
Can I run a Broadleaf store on Svelte Commerce today?
Cart, checkout and sign-in are wired against Broadleaf Microservices and no gaps are recorded, so it is one of the more complete connectors. Check your cart totals first: Broadleaf’s published schema omits them, and a gateway that follows it strictly would show zero.
How do I switch Svelte Commerce to Broadleaf?
Remove the connectors the storefront ships with, install @misiki/broadleaf-connector, set PUBLIC_BROADLEAF_API_URL in .env and start the dev server. vite.config.ts resolves whichever connector is installed, so no file in the storefront changes.
Does the connector work with Broadleaf 5.x or 6.x?
No. It targets Broadleaf Microservices, described by 41 OpenAPI 3.0.3 documents. The 5.x/6.x monolith publishes no versioned REST contract, so there was nothing to wire against.
Sources
BROADLEAF.md, read on ; CONNECTORS.md, read on ; the connector’s source at 729560e. Where they disagree with this page, they are right. Broadleaf is a trademark of its owner, named only to describe compatibility; see trademarks.