← Back to projects

AI Product Configurator

A guided configurator running inside a store somebody else already operates

ScopeConfigurator front end & theme integration
TypeE-commerce
StackReact / TypeScript / Vite / Zustand
StatusProprietary · Client Project

This is a client project. The write-up is intentionally generalized: no client, brand, or product names, no data, and no source code are shown. What follows is my own account of the constraints, the architecture, and the decisions I made.

PRODUCT CONFIGURATOR EXISTING THEME ONE BUNDLE MOUNTED INTAKE → AI CHAT → CONFIGURE → STORE CART
01Overview

This is a guided configurator for a made-to-order product assembled from interchangeable components. A shopper answers a short intake, talks to an AI assistant that suggests components, arranges them on a live stage, then adds the finished configuration to the store cart as real line items.

It is not a new site. It ships as one JavaScript bundle and one stylesheet, dropped into a Shopify OS 2.0 theme the client already runs and mounted by a Liquid section. The store keeps working exactly as it did before, and the merchandising team can place an entry point on any page without a developer.

I built the configurator front end and its integration into the theme: the intake wizard, the AI chat surface, the interactive stage and its drag physics, the cart handoff, and the style isolation that stops the two codebases from fighting each other.

02Working Inside a Live Store

A live store is somebody else’s production environment. It has its own CSS, its own JavaScript, its own release process, and revenue running through it. Every decision in this section exists because of that.

The build emits a single self-executing bundle and a single stylesheet directly into the theme’s asset directory, with the output directory never emptied, so a build cannot delete an asset it does not own. The bundle targets a recent JavaScript baseline rather than a down-levelled one: the older target emitted helper code that collided with a global the theme’s existing jQuery already owned.

Style isolation is specificity, not encapsulation. Every utility class compiles under the mount element’s ID selector, which outranks the theme’s own stylesheet. There is no shadow DOM, so the configurator still inherits the store’s fonts and colour and reads as part of the shop, while nothing it defines escapes into the rest of the page.

The theme hands over data instead of the bundle re-fetching it. A Liquid section renders a JSON block carrying shop, customer, cart and route information, and the bundle reads that on mount. Entry points work by delegated listener on a data attribute, so any button in the theme opens the configurator without a code change on my side.

03Key Features
Intake Before AI
A short start screen captures the mode and a few questions — who it is for, the occasion, the material, the theme. The assistant opens with that context instead of a blank prompt.
AI Assistant
Messages go to a backend endpoint through the platform’s app proxy and come back with a reply, product suggestions, and suggested follow-ups. The model call stays server-side, so no API key ships in the bundle.
Live Configuration Stage
Components render on a rotatable stage. Drag to spin it, drag components between slots, tap a personalisable component to add an engraving.
Hand-Written Drag Physics
Spin carries momentum after release and decays under friction until it comes to rest. Motion is disabled outright when the visitor prefers reduced motion.
Cart Handoff
A finished configuration becomes real cart line items through the store’s own cart API, with hidden properties recording session and position, and readable properties for name, engraving, gift wrap and notes.
Merchant-Configurable Section
The Liquid section exposes its initial view, hero image and trust badges to the theme editor, so the client changes them without touching code.
04Technical Architecture

React and TypeScript, built by Vite in library mode to one self-executing bundle. One entry point, one stylesheet, no code splitting: a theme serves each asset by name from its own pipeline, and extra chunks would need loader plumbing the theme does not have.

A single state store holds the whole session — current view and entry point, wizard step and completed steps, intake answers, the configuration itself, chat history and session id, per-action loading flags, and a transient toast. Keeping it in one place means the chat, the stage and the review step all read the same configuration object instead of syncing copies of it.

Server state runs through a query client with a five-minute stale window and a single retry. Product and cart reads use the store’s own AJAX endpoints; AI calls go to the backend through the app proxy, which keeps them same-origin. Nothing calls the storefront API directly, so no storefront token is exposed in the bundle.

The stage is hand-written rather than a drag library. Pointer events feed an angle delta for the spin, a velocity that decays each frame, and a nearest-slot search with a fixed drop radius for reordering. Components pack without gaps, so a drop on empty space appends to the end of the chain. A generic drag library gives you list reordering; this needed reordering around a curve inside a rotating frame of reference.

Locally the bundle runs against a mock server standing in for the proxy, so the front end can be developed and demonstrated without the store or the AI backend in the loop.

05Tech Stack
ReactConfigurator UI
TypeScriptTypes across store, services & stage
Vite (library mode)Single-bundle build into the theme
ZustandOne session store
TanStack QueryServer state, caching & retry
Tailwind CSSUtilities scoped to the mount element
Shopify LiquidSection, JSON data handoff, asset delivery
Shopify AJAX APICart and product reads
App ProxySame-origin path to the AI backend