Svelte Commerce × Shopify
Svelte Commerce on Shopify
The Shopify connector is scored out of 27, not 43: several storefront services have no equivalent in the Shopify API surface it targets. Cart, checkout and sign-in are wired — but every request goes through a proxy route you have to write.
- 16/27 services wired
- @misiki/shopify-connector 1.1.0
- Cart wired
- Checkout wired
- Sign-in (auth) wired
What works on Shopify today
Cart, checkout and sign-in are wired, but it does not run as installed. The connector sends every request to a /proxy/shopify/ route on the storefront’s own server, with the Shopify request path encoded in it, and Svelte Commerce ships no such route — only one for Bagisto. Until you write it, nothing reaches Shopify.
Cart
Wired: issues a real request to Shopify.
Checkout
Wired: issues a real request to Shopify.
Sign-in (auth)
Wired: issues a real request to Shopify.
Known gaps: review, wishlist, vendor, page, profile, country
16 of 27 services wired, read from CONNECTORS.md on ; npm may carry a newer patch. How coverage is measured.
What the connector calls on Shopify
The connector calls Shopify’s Storefront GraphQL API as POST /graphql.json for the catalogue, cart, checkout and customer, and a few Admin REST paths such as /shop.json, /customers/{id}.json and /price_rules.json, every one of them through the storefront’s /proxy/shopify/ route.
The connector attaches no store token itself and leaves that to the proxy route; a shopper signs in with the Storefront mutation customerAccessTokenCreate, the returned access token is kept in localStorage under customerAccessToken, and it is sent as the customerAccessToken GraphQL variable rather than as a header.
| Service | What it requests |
|---|---|
product | query listProducts (products(first, query)) and query getProductByHandle (product(handle)) |
search | query search (search(query, first: 50, types: [PRODUCT]), reading totalCount) |
category | query getCollections (collections(first)), query getCollectionByHandle and query getCollectionProducts (collection(handle) { products(first) }) |
cart | mutation cartCreate, query getCart, mutation cartLinesAdd, cartLinesUpdate, cartLinesRemove, cartDiscountCodesUpdate and cartBuyerIdentityUpdate |
checkout | query getCart for cost and deliveryGroups(first: 1) delivery options; mutation cartAttributesUpdate (with cartNoteUpdate for cash on delivery) to read the cart’s checkoutUrl |
order | query getCustomerOrders (customer(customerAccessToken) { orders(first) }) and query getOrder (node(id)) |
auth | mutation customerAccessTokenCreate, query getCustomer (customer(customerAccessToken)) and mutation customerCreate |
payment-method | query { shop { paymentSettings { acceptedCardBrands supportedDigitalWallets } } } |
Shopify rules the connector follows
- The request paths carry no API version: Storefront calls go to
/graphql.jsonand Admin calls to paths such as/shop.json, and the/admin/api/2026-01prefix defined in the base service appears only in a commented-out line. - Every payment method the storefront offers, cash on delivery, Razorpay, PhonePe, PayPal and Stripe, sets a
return_urlcart attribute and hands back the cart’scheckoutUrl, so the shopper pays on Shopify’s own checkout; cash on delivery also writes a cart note and redirects the browser itself. - The product list builds a Shopify search string from
title:,tag:,vendor:andcollection:terms, and reports the number of products it got back as the count, because the query asks for no total. - A stored cart id is used only if it contains
gid://shopify/Cart/; anything else, or a cart Shopify no longer returns, makes the connector create a new cart, and the id is saved inlocalStorageas bothshopify_cart_idandcart_id. - Order history needs the signed-in shopper’s token: without
customerAccessTokeninlocalStoragethe order list returns empty without making a request.
Read from the source of misiki-in/shopify-connector at commit 6e5fed6 of . Where the code has changed since, the code is right.
Quick start
From nothing to a Svelte Commerce storefront reading Shopify. You need Node.js and a Shopify to point it at; the storefront holds no data of its own.
Clone it, choose the connector, point it at Shopify
# 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/shopify-connector
# 3 — point it at your Shopify store
echo PUBLIC_SHOPIFY_API_URL=your-store.myshopify.com >> .env
echo PUBLIC_SHOPIFY_ACCESS_TOKEN=shpat_... >> .env
echo PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=... >> .env
# 4 — run it
npm run dev The guide removes only @misiki/litekart-connector. A fresh clone’s package.json also lists @misiki/vendure-connector, and with two connectors installed and neither of them Litekart’s, the build stops and asks for PUBLIC_CONNECTOR — so this removes both. This starts the storefront, but read the limitations: the connector needs a /proxy/shopify/ route that the storefront does not ship.
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_SHOPIFY_API_URL | Yes | Your store’s myshopify.com domain. Shopify is keyed on a domain rather than a URL, so any https:// you include is stripped. Boot fails, naming this variable, if it is missing. |
PUBLIC_SHOPIFY_ACCESS_TOKEN | No | The guide’s example is an Admin API access token, shpat_…. Handed to the connector at boot — and to every visitor’s browser; see the limitations. |
PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN | No | A Storefront API access token, handed over the same way. |
PUBLIC_SHOPIFY_PROXY_URL | No | Read at boot and stored by the connector, for stores fronted by a proxy. In 1.1.0 and 1.1.1 the request path is fixed at /proxy/shopify/, so setting it changes nothing yet. |
PUBLIC_CONNECTOR | No | Only when more than one connector is installed: @misiki/shopify-connector names the one this build runs on. |
Shopify is one of four backends init.ts configures by hand rather than by forwarding every PUBLIC_SHOPIFY_* variable: it passes the domain, the two tokens and the proxy URL to setShopifyCredentials, in that order.
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 Shopify
- Create the access tokens in Shopify: an Admin API token (the guide’s
shpat_…) and a Storefront API token. - Write a server route at
/proxy/shopify/[...path]in the storefront. The connector base32-encodes the Shopify request path into the route’s path and says which API it wants in anX-Shopify-Api-Typeheader —adminorstorefront— but attaches no token itself; the route has to add the right one and forward the request. The storefront’s/proxy/bagisto/route is the nearest pattern to copy.
How the integration works
Shopify is keyed on a store domain rather than a URL. At boot, init.ts strips any https:// from PUBLIC_SHOPIFY_API_URL and passes the domain, the Admin and Storefront tokens and the proxy URL to the connector’s setShopifyCredentials, in both the server and the client hook.
The connector sends every call — Admin API or Storefront API — to /proxy/shopify/<base32-encoded path> on the storefront’s own origin, marked X-Shopify-Api-Type: admin or storefront. It never sends a token itself: the proxy is expected to. Svelte Commerce ships a proxy route of this kind for Bagisto, not for Shopify.
Limitations on Shopify
- Nothing reaches Shopify until you add a
/proxy/shopify/server route: the connector sends every request there, and the storefront does not ship one. - Scored out of 27 rather than 43: several storefront services have no equivalent in the Shopify API surface this connector targets.
- The guide puts an Admin API token (
shpat_…) inPUBLIC_SHOPIFY_ACCESS_TOKEN. SvelteKit sendsPUBLIC_variables to the browser, so every visitor could read it and call Shopify’s Admin API with it. A server route is the place for that token, not aPUBLIC_variable.
Troubleshooting Shopify
| When you see | What to do |
|---|---|
Every call fails with a 404 on /proxy/shopify/… | The storefront has no Shopify proxy route. Add a server route at /proxy/shopify/[...path] that decodes the base32 path, adds the Admin or Storefront token according to X-Shopify-Api-Type, and forwards the request to Shopify. |
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.
Offer a sandbox or a correctionFAQ
Questions about Svelte Commerce on Shopify
Can I run a Shopify store on Svelte Commerce today?
Not as installed. Cart, checkout and sign-in are wired, but the connector sends every request to a /proxy/shopify/ route on the storefront’s server, and Svelte Commerce does not ship one. Writing that route — and keeping the Admin token in it, out of PUBLIC_ variables — is the missing step.
How do I switch Svelte Commerce to Shopify?
Remove the connectors the storefront ships with, install @misiki/shopify-connector, set PUBLIC_SHOPIFY_API_URL in .env and start the dev server. vite.config.ts resolves whichever connector is installed, so no file in the storefront changes.
Why is Shopify scored out of 27 instead of 43?
Several of the storefront’s 43 services have no equivalent in the Shopify API surface the connector targets, so they are not counted. Of the 27 that are, 16 are wired; reviews, wishlist, vendors, CMS pages, profile and countries are the gaps.
Sources
SHOPIFY.md, read on ; CONNECTORS.md, read on ; the connector’s source at 6e5fed6. Where they disagree with this page, they are right. Shopify is a trademark of its owner, named only to describe compatibility; see trademarks.