A cart on a site with no server
Letting Shopify own the cart, and keeping only the receipt in localStorage.
The cart is now real: you add paintings on the site, the drawer shows live prices, and you only leave for the payment step. There is still no server anywhere in this — the site is a folder of HTML files on a CDN.
The trick is deciding what the browser is allowed to know.
The browser stores one thing: the cart’s id. Not the lines, not the prices, not the totals. A Shopify Storefront API token — public by design, unlike the admin credentials the build uses — lets the page create a cart, add lines to it and read it back. Shopify owns the data; the site owns a pointer to it.
That removes a whole category of bug. There’s no local total that can drift from the real one, and no way to check out with a price the store doesn’t agree with. It also means the cart survives a browser refresh and a change of page, because the state was never in the page.
There is a cache, but it’s for painting, not for truth. A copy of the last
known cart sits in localStorage so the header badge and the drawer render
instantly on load; a request then reconciles it against Shopify. If that request
comes back saying the cart is gone — completed, expired — the id is dropped and
the next add starts a fresh one. If it fails for network reasons, the cache
stays put. Those two failures look similar and must be handled differently.
The bit I got wrong first. Stock is enforced server-side, so re-adding a sold-out painting succeeds — it just doesn’t change anything. The button happily said “Added”. Now it compares the quantity before and after and says “Already in cart” when nothing moved. Never report success for an action that didn’t happen; that’s twice on this project now.
The checkout handoff still leaves the domain, because the store is shared with other artists and the checkout lives there. That one isn’t a technical problem and can’t be solved with code.