Inspiration
Every e-commerce "personalization" story ends at a recommendations rail. The store looks the same for everyone: same nav, same hero, same homepage, with a "You might also like" shelf stapled on. Netflix doesn't just recommend shows inside a fixed grid; it redesigns the entire grid around you. We asked why online shopping doesn't work that way.
And we wanted the loop closed both directions. If the store learns from the shopper, the shopper should be able to talk back to the store. Ask it why it's showing you something, tell it what you actually want, and let it shop on your behalf. Not a chatbot bolted on the side. An agent that can actually operate the store.
What it does
Silicon Shoppers is a personalization engine, demoed inside SoCal Atelier, a fashion storefront we built:
First-paint personalization. An H&M-trained model reads purchase history, earns the shopper a deterministic persona (Price Hunter, Trend Seeker, Mission Shopper, Brand Loyalist), and emits a full layout document, atelier.store_layout.v1, covering nav order, hero ad, homepage rails, listing sort, filters, badges, and checkout variant. The store arrives already merchandised for you. Live adaptation. An OTTO-trained browsing model watches the session (views, filters, sorts, bag adds) and refreshes the layout every four minutes. Rearranging you can see. Layout changes play in staged animations: nav slides first, the hero swaps with its own transition, homepage rails reorder pass by pass, each tagged with what moved and why. Explainable AI. Every decision carries a reason string. "Why am I seeing this?" gets a real answer. The concierge. A DeepSeek-powered chat bubble that rearranges the store on command ("make this more men-friendly, navy forward"), answers questions grounded in your actual shopper profile ("what's my most purchased size?"), and acts as a shopping agent. "Buy the wool trouser in black, size M" becomes an item in the bag, a checkout confirmation, and a paid order through our demo Visa flow. Snowflake backbone. Model inputs, layout outputs, the full event stream, and live shopper layouts all persist to Snowflake; the refresh loop executes the frozen model.
How we built it
- Storefront + shell. Next.js 16 (Turbopack) storefront rendered inside a simulator shell: persona panel on the left, store in a fake-browser frame, live terminal underneath narrating every tracker event, layout step, LLM call, and payment.
- Layout as data. The whole storefront renders from one validated JSON contract (atelier.store_layout.v1), so a model, the refresh loop, or the concierge all mutate the same typed document.
- Staged animation engine. A diff of two layouts produces ordered stages (nav, hero/ads, home blocks, listing), each applying inside document.startViewTransition with scroll and flash highlights.
- The agent pipeline. This is where we spent the most effort. The concierge streams NDJSON through /api/chat. Model replies can carry an <<>> marker. Then a layered honesty system kicks in:
- Prompt: claims must be backed by emitted actions
- Parser: tolerates fenced JSON, trailing prose, partial markers
- Catalog validation: ids, colors, sizes checked against real products
- Prose recovery: if the model says "I've added the Wool Trouser" but emits nothing, we extract the real product from its sentence and actually add it
- Claim audit: every "I did X" in the reply is compared against what actually executed; mismatches get an honest correction appended
- Checkout that can't lie. Payment is gated on the shopper's own words (a typed "yeah I'm done" or a button press, never a phrase inside "purchase the shirt"). Auto-pay is a live toggle: flipping it mid-session starts or cancels the agent's capture, manual clicks win the race, and a captured session can never charge twice.
- Testing. 111 Vitest cases including scripted multi-turn shopper sessions that drive the real pipeline: buy, browse claims, phantom adds, double-payment races, second orders in one chat.
Challenges we ran into
- LLMs lie. The model confidently claims adds, checkouts, and payments it never performed. Our fix: trust state, not prose. Every claim is audited, and missing actions are recovered from the model's own words or honestly reported.
- Ambiguous confirmations. "Nope" after "done shopping?" means keep browsing; "yeah I'm done" means pay. We handle short typed answers locally like button clicks, so the model never gets to interpret a yes/no.
- Checkout races. Auto-pay timers versus manual Visa clicks versus stale sessions produced a real double-capture bug. Now capture is guarded by phase and cleared sessions, making double-charge impossible.
- Structure, not shelves. Personalizing layout meant defining the versioned contract, the staged animation, and an intent parser that knows "expensive" is not "sale" and "nothing too expensive" means budget.
Accomplishments that we're proud of
- A chatbot that physically can't lie. Every claim the concierge makes is audited against real store state before it reaches the shopper. If the model says "added to your bag" and nothing was added, we either recover the action from its own words or tell the shopper the truth. Most agent demos trust the model's prose; ours verifies it.
- Checkout that can't double-charge. Manual clicks, auto-pay timers, and mid-flight toggles all race each other, and the guards we built make a second capture mathematically impossible. We found the bug live during a demo session and fixed it properly.
- A real agent loop, end to end. "Buy the wool trouser in black, size M" resolves against a real catalog, lands in a real bag, waits for a real confirmation, and produces a real order id. Typed "nope" keeps you shopping. Second orders in the same chat start clean. No theater.
- Personalization of structure, not shelves. The whole storefront (nav, hero, rails, sort, filters, badges, checkout variant) renders from a single versioned contract that three different writers can mutate: the history model, the live session model, and the shopper's own voice.
- A store you can watch think. The terminal narrates every event, layout stage, and model call, and the rearranges play as staged animations rather than silent snaps. Personalization you can see is personalization judges can grade.
- 111 tests, including scripted conversations. Multi-turn shopper sessions drive the real pipeline: phantom adds, checkout races, ambiguous yes/no, recovery from missing actions. The failure modes we hit in live demos are now regression tests.
What we learned
Personalization is a systems problem as much as a model problem. The layout contract, event plumbing, and animation matter as much as the scores. And LLM agents need distrustful plumbing: the prompt is a suggestion, but validation, recovery, and state-audited claims are what make one demo-ready.
What's next for Silicon Shoppers
- Richer personas: style clusters from embeddings, not just behavioral rules
- Collaborative signals across shoppers ("shoppers like you browse…")
- Real payments via the Visa APIs we mocked, and production Snowflake event ingestion
- Voice concierge: the same agent, hands-free
Built with
Next.js 16 · TypeScript · Zustand · Nebius DeepSeek-V4-Flash / Gemini · Python model pipeline · Snowflake · H&M + OTTO datasets · Vitest
Built With
- api
- python
- snowflake
- typescript
Log in or sign up for Devpost to join the conversation.