All websites

09 / Case study

Shopz / 2026

Shopz — a whole shop in one pair of hands, from cart to parcel locker

A bike shop demo in Astro, Sanity and Shopify: a custom front end and checkout, prices checked on the server, InPost parcel lockers with a map and a ShipX shipment. On desktop, Lighthouse gives 100 for performance.

Role
Design and development / my own demo
Year
2026
Scope
  • Front end
  • Shopify (Storefront and Admin API)
  • Checkout
  • InPost
  • Sanity
  • Performance
Disciplines
  • Astro
  • Shopify
  • Sanity
  • InPost
  • three.js
  • Cloudflare Workers
Visit site
The Shopz home page: a cyclist on a forest road and the line “Jedź dalej. Wracaj później.” (Ride further. Come back later.)

The idea

An online shop is usually the work of several people: one builds the theme, another connects payments, another the courier. Shopz shows the whole thing done by one person: the design, the catalogue, the cart, the checkout, shipping and the panel for editing content.

It is a fictional bike shop: 49 products from six brands, bikes and accessories. The pages are static HTML from Astro on Cloudflare Workers. Shopify holds prices, variants and stock, and Sanity everything else: descriptions, photos, specs and the home page sections.

The Gravel category: brand and price filters, sorting and a grid of bikes with a discount
The filters work at once, and their state is in the page address.

Catalogue and product

The list has filters for category, brand, price, size, colour, availability and sales. Their state is saved in the address, so a result can be shared as a link, and without JavaScript the list is simply complete. Search opens with ⌘K.

The product page loads the price and stock straight from Shopify, so it shows what is in the shop right now. The bike photos are renders of the same 3D model the bike section on the home page uses.

The Nordvelo Strada GRX bike page: a photo, colour and frame size by height, availability and an “Add to cart” button
Price and stock straight from Shopify.

Cart and checkout

The cart runs on Shopify’s Cart API. An expired cart rebuilds itself, and when Shopify doesn’t answer, the cart carries on in the browser.

I built the checkout myself instead of using Shopify’s: four steps on one page, and invoices for companies, where the tax ID is checked against its checksum and the company name and address load from the Polish VAT register. The server prices the order again, from Shopify’s data, and never trusts the amounts sent by the browser. Only then does it create the order in Shopify, and stock goes down at once.

Diagram: the cart on the site sends the order to a Cloudflare Worker, which prices it again and checks the parcel locker, then creates the order in Shopify and the shipment in InPost; the shipment number and confirmation come back
The price is set on the server, not in the browser.

InPost

A parcel locker is picked on InPost’s map (Geowidget), whose script loads only when it is first opened, or by typing its code. The server checks the code, because InPost’s points API doesn’t answer browsers on other domains.

After the order, the server creates a ShipX shipment: to a locker, with the size matched to the contents, or by courier, in a bike box. The shipment number goes into the Shopify order. A bike won’t fit in a locker, so both the form and the server block that option. In the demo, InPost runs on a test account (sandbox).

The “Choose a parcel locker” window over the checkout: an InPost map with points in Warsaw and a search box
The locker map loads only when it is needed.

Payments

BLIK, card, instant transfer and 0% instalments are in the form, but this is a demo shop: nothing is charged. A payment gateway (such as Przelewy24, PayU or Shopify Payments) plugs into a step that already exists. The order is created on the server after the price check, so the payment gets an amount that can’t be changed in the browser.

Shopify and Sanity in sync

When a product or stock changes in Shopify, a webhook signed with HMAC wakes the Worker. It fetches the current data from the Admin API, saves it in Sanity and asks for a rebuild, at most once a minute. From a change in Shopify to a new version of the shop takes about 2 minutes.

The “Look inside” section: an e-bike taken apart in 3D, with a label on the 500 Wh battery
The bike in 3D: three.js loads only one screen before this section.

Performance

The home page loads 20 KB of JavaScript. three.js arrives only one screen before the bike section, and only on devices that can handle it (WebGL2, at least 4 GB of memory, no data saving and no reduced motion). Everyone else sees a photo and a list of parts.

Before any scrolling, the home page loads 7 images instead of 14 on phones and 21 on desktop. The first screen’s photo comes from the shop’s own domain, in AVIF. The font is split in two files: the set with Polish letters (51 KB) loads at once, and the rest only when a page uses it.

Lighthouse on desktop (measured on 2 November 2026): 100 for performance, accessibility and best practices, LCP 0.6 s, layout shift 0. In the mobile simulation, performance is 96. SEO isn’t 100 only because the demo shop is deliberately kept out of search engines; the product and offer structured data are in place. axe-core (WCAG 2.2 AA) finds no errors on 10 pages at two widths, and over 170 automated tests check the shop’s logic.

Questions

  • Why Shopify, and not a shop from scratch?

    Shopify handles the riskiest part of a shop: prices, stock and orders. The design and content are custom, in Astro and Sanity, so the shop doesn’t look like a template and loads fast.

  • Do payments work in Shopz?

    No, it is a demo: BLIK, card, transfer and instalments are for show and nothing is charged. In a real shop, a payment gateway (such as Przelewy24, PayU or Shopify Payments) plugs in where the server already creates the order.

  • Does running the shop need a developer?

    No. Products, prices and stock are changed in Shopify, and descriptions, photos and page sections in Sanity. The shop updates itself after every change.

Tell me what you need.

Reply within 24 h

What is it about?

Please enter your name.

Please enter a valid email address.

Please write a message (min. 10 characters).

Add details: company, timeline, budget
Budget optional

Form data is used only to reply to your message. Privacy policy

SR / Terminal

Tab completes · ↑↓ history · Esc closes