Luxwearz Storefront
A premium leather-goods storefront that builds its own SEO surface — redirects, sitemap, robots and agent-readable twins emitted as real files at build time.
- Client
- Luxwearz
- Category
- Frontend Engineering
- Completed
- 2026-08-14
- Built with
- React.js, TypeScript, Vite, Tailwind CSS, REST API
- Topics
- E-commerce, Frontend, SEO
React SPA Storefront Static Build Live
The customer-facing storefront for a premium leather-goods brand. It ships no backend of its own — every read and write goes to Custom Store Management, the headless commerce platform behind it.
The interesting part is the build
Most storefronts hardcode their SEO surface. This one fetches it from the admin at build time and emits real static files, through five bespoke build plugins:
| What it emits | Built from | What it fixed |
|---|---|---|
.htaccess | operator-managed redirects | 301s that a client-side router simply cannot serve |
sitemap.xml | published catalogue plus evergreen routes | the SPA fallback was serving HTML for the sitemap path, so no valid sitemap existed at all |
robots.txt | the AI-crawler policy set in the admin | crawler rules drifting from what the operator configured |
llms.txt | content feeds | an agent-readable summary of the site |
| per-entity markdown twins | products and pages | agents fetch markdown instead of JavaScript-rendered HTML |
All five fail open. An unreachable API leaves the build green rather than shipping a broken site — deliberate, because a stale sitemap is recoverable and a failed deploy at 2am is not.
Performance decisions, each with a reason
Route-level code splitting. The home route stays eager; thirty-plus others are lazy. One small helper was moved out of the chat module specifically because re-exporting it from the widget dragged the entire chat bundle, markdown renderer included, into the entry chunk on every page load.
The chat widget loads with no fallback UI. Roughly 800 KB with its rendering pipeline, it renders nothing at all until tapped.
Manual vendor chunking keeps the framework core, data fetching, animation and charting in separate named chunks, so the framework stays cached across deploys instead of being invalidated by unrelated changes.
Fonts load without blocking render, with a no-JavaScript fallback, and the API origin is preconnected to protect the largest-contentful-paint measurement.
Talking to the backend
One HTTP client, with the rules written into it:
- The API envelope is unwrapped once in an interceptor, and failures normalise into a typed error carrying a code and a status.
- The cart header is attached only on cart and checkout paths — attaching it globally would trigger a preflight request on every catalogue read.
- Retries apply to idempotent reads only: two attempts with backoff on network failure, server error, or throttling. Writes are never retried.
- An expired session clears auth and the chat token but preserves the guest cart key — otherwise the assistant kept answering as the previous customer.
Shipping it
Continuous integration typechecks and runs unit tests as a hard gate before the build. Deploy is a synchronised file transfer over SSH on push to main, with a retry loop. The backend enforces a merge guard that reads the CI result and blocks any merge that is not green.
Stack
React 18.3 TypeScript 5.5 Vite 5 Tailwind 3.4 Redux Toolkit TanStack Query 5 React Router 6 Radix UI Stripe Elements Framer Motion Vitest
Sixty routes, lazily loaded, over a single static build.