Case Study · 04 of 05

Phones & Laptops Store

A React single-page storefront, rebuilt to run from a static host

Electronics store front page showing phones and laptops with prices in Kenyan shillings
Mosey Technologies — storefront (index.html)

This is the only project here that is not hand-written HTML — it is a React single-page app built with Vite. It is also the project that taught me the most about deployment, because getting a client-side router to work correctly from a sub-folder on a static host is a different problem from getting it to work on localhost.

The brief

A phone and laptop retailer needed a catalogue shoppers could filter by category, read reviews on and order from — with prices in shillings, a cart that survives a refresh, and a checkout step. No server-side rendering, no backend to host: it had to stay a static bundle that can be dropped on any host.

What I built

  • Nine routes — shop, product details, cart, checkout, account, login, register, about and contact.
  • Category browsing through shareable URLs such as /shop?category=phones — phones, laptops, audio, wearables and gaming.
  • Sorting and filtering, including /shop?sort=rating to put the best-reviewed products first.
  • A cart and checkout flow with state persisted in localStorage, so a refresh does not empty the basket.
  • Product pages with customer reviews, and prices formatted in Kenyan shillings.

How it works — and the static-hosting problem

Two things had to change before this could live on GitHub Pages, where the site is served from a sub-folder rather than a domain root.

First, routing. The app reads an injected window.__ROUTER_BASE__ value and passes it to the router as its basename, so every link resolves under /portfolio/projects/phones-laptops/ instead of jumping to the root of the domain.

Second, the service worker. The original worker precached absolute root paths, which are wrong the moment the app is not at the root — it would have failed to install, or worse, served a stale shell. The shipped worker is a deliberate no-op: it takes control, skips precaching, and lets the network serve everything. For a demo site, correct and predictable beats clever.

What I would do next

  • GitHub Pages has no single-page-app fallback, so refreshing a deep link such as /cart returns a 404. The fix is either hash routing or a 404.html redirect shim — I would add the shim.
  • Server-render or pre-render the product pages so they can be indexed as individual pages rather than one app shell.
  • Split the bundle; the main application chunk is around 250 KB and the checkout path alone does not need all of it.