Svelte Commerce × Shopware
Svelte Commerce on Shopware
Shopware’s Store API is one of the cleanest headless surfaces of the 26. The connector carries the cart and the customer’s session in the sw-context-token header, captured and replayed like a cookie.
- 28/43 services wired
- @misiki/shopware-connector 0.4.0
- Cart wired
- Checkout wired
- Sign-in (auth) wired
What works on Shopware today
Cart, checkout and sign-in are wired; coupons are the one recorded gap. The connector found Store API routes to apply and remove a promotion code on a cart, but none to list or validate a code on its own.
Cart
Wired: issues a real request to Shopware.
Checkout
Wired: issues a real request to Shopware.
Sign-in (auth)
Wired: issues a real request to Shopware.
Known gaps: coupon
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 Shopware
The connector calls Shopware’s Store API, a REST API under the single base path /store-api, and leaves the Admin API at /api alone because it needs an OAuth client-credentials grant.
Every request sends the sales channel’s key as sw-access-key (and sw-language-id when one is configured), and the shopper’s session and cart ride on sw-context-token, which the connector reads from each response header or, when CORS hides the header, from the body’s token, then keeps in memory and in localStorage under cart_id.
| Service | What it requests |
|---|---|
product | POST /store-api/product/{id} for one product, after POST /store-api/seo-url turns a handle into its id (routeName frontend.detail.page), then a second POST /store-api/product filtered on parentId for the variants |
search | POST /store-api/search with search, p, page and limit in the body; typeahead uses POST /store-api/search-suggest |
category | POST /store-api/navigation/{type}/{type} for the menu trees and POST /store-api/product-listing/{categoryId} for a category’s products |
cart | GET /store-api/checkout/cart, POST /store-api/checkout/cart/line-item with items: [{ type: 'product', referencedId, quantity }], PATCH on the same path to change a quantity and POST /store-api/checkout/cart/line-item/delete with line-item ids |
checkout | PATCH /store-api/context with the paymentMethodId, POST /store-api/checkout/order, then POST /store-api/handle-payment with orderId, finishUrl and errorUrl, which may return a redirectUrl |
auth | POST /store-api/account/login with { username, password }, POST /store-api/account/register, POST /store-api/account/logout and GET /store-api/context |
order | POST /store-api/order with a criteria body; the list arrives nested under orders |
address | POST /store-api/account/list-address, POST /store-api/account/address, PATCH and DELETE /store-api/account/address/{id}, and PATCH /store-api/account/address/default-billing/{id} or default-shipping/{id} |
Shopware rules the connector follows
- Lists are fetched with a criteria object in the POST body (
page,limit,filter[],sort[],associations), and the connector always addstotal-count-mode: exact, because Shopware’s default ofnonemakes every list report a total of 0. - Every Store API path segment is a 32-character hex id, so a product or category handle is first looked up through
POST /seo-url, matching the path both with and without a trailing slash. - Sort tokens are mapped to a fixed list of product fields (price sorts on
cheapestPrice, popularity onsales), and an unknown token is dropped, since Shopware answers an unknown sort field with a 400 error. - The listing and search routes page with
prather thanpage, so the connector sends both with the same value. - The context token is always overwritten with the newest one seen, because
POST /account/logoutreturns a new anonymous token and keeping the old one would restore the session that was just closed.
Read from the source of misiki-in/shopware-connector at commit e0d17b9 of . Where the code has changed since, the code is right.
Quick start
From nothing to a Svelte Commerce storefront reading Shopware. You need Node.js and a Shopware to point it at; the storefront holds no data of its own.
Clone it, choose the connector, point it at Shopware
# 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/shopware-connector
# 3 — point it at your Shopware shop
echo PUBLIC_SHOPWARE_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_SHOPWARE_API_URL | Yes | Your Shopware shop’s URL; the connector calls its Store API. Boot fails, naming this variable, if it is missing. |
PUBLIC_SHOPWARE_ACCESS_KEY | No | The sales channel’s access key, sent as sw-access-key. It chooses the sales channel and is meant for storefront use. If it is unset, PUBLIC_SHOPWARE_API_KEY or PUBLIC_SHOPWARE_ACCESS_TOKEN is read in its place. |
PUBLIC_CONNECTOR | No | Only when more than one connector is installed: @misiki/shopware-connector names the one this build runs on. |
init.ts hands the connector every PUBLIC_SHOPWARE_* variable that is set, camel-cased. The guide also lists PUBLIC_SHOPWARE_API_SECRET, PUBLIC_SHOPWARE_STORE_ID and PUBLIC_SHOPWARE_CHANNEL_ID; the connector’s source does not read them — the sales channel is chosen by the access key alone.
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 Shopware
- Use a sales channel’s access key: the Store API chooses the sales channel by the
sw-access-keyheader, and there is no route that picks a store by ID.
How the integration works
The connector speaks Shopware’s Store API, the shopper-facing half of Shopware’s API. Every request carries the sales channel’s sw-access-key; the cart and the signed-in customer live in the sw-context-token header, which the connector captures from responses and replays like a cookie.
Limitations on Shopware
- Coupons: not wired — the connector found Store API routes to apply and remove a promotion code on a cart, but none to list or validate a code on its own.
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 Shopware’s maintainers: Is there a Store API route for promotion or voucher lookup — not just applying one to a cart? The connector found apply and remove, but no way to list or validate a code on its own.
Offer a sandbox or a correctionFAQ
Questions about Svelte Commerce on Shopware
Can I run a Shopware store on Svelte Commerce today?
Cart, checkout and sign-in are wired against Shopware’s Store API, and coupons are the only recorded gap. Like every connector, it has not been run against a live production Shopware store.
How do I switch Svelte Commerce to Shopware?
Remove the connectors the storefront ships with, install @misiki/shopware-connector, set PUBLIC_SHOPWARE_API_URL in .env and start the dev server. vite.config.ts resolves whichever connector is installed, so no file in the storefront changes.
How does the cart keep its session on Shopware?
Through the sw-context-token header. Shopware returns it with the cart and the customer session; the connector captures it and sends it back on later requests, the way a browser replays a cookie.
Sources
SHOPWARE.md, read on ; CONNECTORS.md, read on ; the connector’s source at e0d17b9. Where they disagree with this page, they are right. Shopware is a trademark of its owner, named only to describe compatibility; see trademarks.