Full-stack retail operations platform for a UK luxury jewellery business — replacing fragmented spreadsheets, disconnected tools, and manual processes with a single intelligent system.

Luxury jewellery retail runs on relationships, precision, and trust. But behind the counter, operations at Intouch were held together by disconnected systems — Shopify for e-commerce, spreadsheets for inventory tracking, manual notebooks for repairs, and no unified view of who their customers were or what they'd bought.
Staff couldn't answer basic questions without switching between three tools. Marketing campaigns meant exporting CSVs to third-party platforms. Physical inventory counts took entire days with no way to reconcile against digital records. And when a customer called about a repair, the answer was “let me check and call you back.”
The platform needed to:
Off-the-shelf retail platforms couldn't deliver. Generic CRMs lack the domain-specific features — repair lifecycle management, consignment tracking, buying-in slips. Jewellery-specific solutions are dated, inflexible, and don't support AI or RFID. Intouch needed a purpose-built platform built around their specific operations.
The most common question from staff was some variation of “Who is our best customer?” or “What's our most popular product type?” Traditional dashboards require knowing where to click. We built something better — a conversational interface where staff ask questions in plain English and get answers instantly.
The AI query pipeline works in stages:
Natural language to SQL
The user's question is sent to Google Gemini 2.0 Flash with a complete schema description. Gemini generates a valid PostgreSQL query — SELECT only, never write operations. Validated server-side before execution.
SQL results to natural language
Raw results pass through a second Gemini call with formatting instructions tuned to the query type. Customer spending queries get one format; product recommendations get another.
Conversation persistence
Every exchange is stored with full metadata — generated SQL, raw results, and formatted response. Follow-up questions have full context. Ask "Who's our top spender?" then "Show me their history" — the system knows who "their" refers to.
Fallback intelligence
When Gemini generates invalid SQL, the system falls back to hand-crafted queries for common patterns — loyalty analysis, product searches, spending breakdowns — rather than returning an error.
Dynamic data visualisation
The pipeline generates a visualisation config specifying chart type, axis mappings, and value formatting. Ask "Show me sales by product type" and you get an interactive pie chart, not a paragraph.
No dashboards to learn — just ask a question.
“Who is our most loyal customer?”
“Sarah Chen, with £12,400 across 23 orders”
Full conversation persistence — follow-up questions have context
“Who is our most loyal customer?”
“Sarah Chen, with £12,400 across 23 orders”
Full conversation persistence — follow-up questions have context
Retail operations are full of repetitive sequences — send a follow-up email 3 days after a repair is completed, notify the manager when a high-value item needs approval, trigger a marketing campaign when inventory drops. Rather than hard-coding these, we built a drag-and-drop workflow builder.
The builder is powered by React Flow, giving users a canvas to compose automation visually:
Trigger nodes
What starts the workflow — e.g. "repair status changes to complete"
Condition nodes
Branching logic — e.g. "if repair cost > £500"
Action nodes
What happens — send email, wait 3 days, notify manager
AI copilot
Describe in plain English — Claude generates the workflow config
The workflow execution engine handles the runtime. An event trigger map covers 20+ domain events. When any API endpoint creates or updates an entity, the engine finds all active workflows with a matching trigger and fires them asynchronously. Steps execute sequentially with context chaining — each step's output feeds into the next via template variables that resolve at execution time.
20+ action handlers cover the full operational surface — send email, create customer, update repair status, add tags, send webhooks, and more. Workflow runs are fire-and-forget — the originating API call returns immediately.
Describe the automation in English — Claude builds the workflow.
Drag-and-drop design with fire-and-forget async execution
A retail platform can't go down during peak hours. The caching layer was designed with a hard constraint: Redis being unavailable must never cause an error visible to users.
Upstash Redis provides the caching and rate-limiting infrastructure, but every cache operation is wrapped in a graceful degradation pattern:
Cache-aside reads
Check Redis first. On a hit, return cached data. On a miss, query Supabase, return the result, and backfill the cache asynchronously — the user doesn't wait for the write.
Tiered TTLs
Active orders cache for 60 seconds. Product catalogues cache for 30 minutes. Reference data caches for 24 hours. Each domain has a tuned expiry.
Sliding-window rate limiting
Login attempts, API calls, and sensitive operations are rate-limited using Redis sorted sets. If Redis is down, rate limiting is bypassed — availability over strict protection.
Pattern-based invalidation
When a product is updated, all product-related cache keys are cleared by prefix. No stale data, no manual key tracking.
Availability verified before every operation
Return cached data instantly
Fall through to database
Users experience slower responses, never errors — availability over strict enforcement
Marketing in luxury retail is personal. Blast emails don't work when your customers expect to be known. The outreach system implements a segment-then-campaign pattern that lets the team target precisely.
Audiences
Dynamic customer segments defined by 26+ filter types — spending thresholds, purchase recency, product preferences, loyalty status, location, tags, and more. Filters are composable and member counts refresh automatically.
Campaigns
AI-generated email content targeting a selected audience. Covers creation, sending via Resend with per-recipient tracking, and real-time analytics for opens, clicks, and unsubscribes.
Audiences are dynamic customer segments defined by 26+ filter types stored as JSONB — spending thresholds, purchase recency, product preferences, loyalty status, location, tags, and more. Filters are composable: combine any number of criteria to build a segment. Member counts are cached and refreshed on filter changes.
Campaigns target an audience with email content that can be AI-generated. The outreach pipeline covers campaign creation, audience selection, optional AI content generation based on audience characteristics, sending via Resend with per-recipient tracking, and real-time analytics for opens, clicks, and unsubscribes.
Physical inventory counts in a jewellery store are high-stakes — every item is valuable, and discrepancies matter. Manual counts took the team an entire day and were prone to human error. RFID scanning reduces this to minutes.
The platform integrates with SimpleRFID through a purpose-built sync layer:
Product sync queue
When a product is created or updated, it's queued with a "pending" status. Product creation never blocks on sync success — the queue decouples the two systems.
Cron-based processing
A Vercel Cron job runs every 5 minutes, picks up pending items, and pushes them to the SimpleRFID API. Failed syncs are retried up to 5 times with the failure reason logged.
Token management
SimpleRFID uses OAuth with expiring tokens. A dedicated token manager handles authentication, automatic refresh, and caching — the sync layer never deals with auth directly.
Scan comparison
Staff trigger a scan and the platform compares what was physically scanned against what the database expects. Missing items, unexpected items, wrong locations — all surfaced immediately.
The key architectural decision was making the sync queue resilient to failures. A SimpleRFID outage doesn't affect product creation. The queue drains when the service recovers. Product data is the source of truth; RFID is a downstream consumer.
A luxury jewellery store needs polished documents — repair tickets, invoices, buying-in slips, cash receipts. And the till needs to print receipts without a desktop printer driver.
Server-side PDFs
@react-pdf/renderer produces repair tickets, sales invoices, buying-in slips with valuation details, and cash slips for safe transactions.
Thermal printing
A dedicated Node.js print server speaks ESC/POS directly. The web app sends print jobs via HTTP, bridging a cloud-hosted PWA to physical retail hardware on the local network.
Server-side PDF generation uses @react-pdf/renderer to produce repair tickets with item details and cost breakdowns, sales invoices with line items and totals, jewellery and watch buying-in slips with valuation details, and cash slips for safe transactions.
Thermal receipt printing runs on a dedicated Node.js print server that speaks the ESC/POS protocol directly. The web app sends print jobs via HTTP; the print server translates them to thermal printer commands. This bridges the gap between a cloud-hosted PWA and physical retail hardware on the local network.
Swipe for more →
Next.js 16 / React 18 / TypeScript / Tailwind CSS / Radix UI
Next.js API Routes + webhook ingestion layer
Supabase (PostgreSQL + Realtime)
Upstash Redis (cache-aside + rate limiting)
Custom JWT (jose) with cookie-based sessions + PIN login
Google Gemini 2.0 Flash + Anthropic Claude + OpenAI
Shopify (bidirectional sync)
SimpleRFID (queue-based sync + scan comparison)
Resend API + React Email templates
React Flow (visual builder) + Supabase (execution)
@react-pdf/renderer + ESC/POS print server
Vercel (Edge Network)
Rather than building static dashboards that answer predetermined questions, the AI pipeline lets staff ask anything about their data in natural language. Gemini generates SQL, executes it, and formats the response — all in under 2 seconds. No feature requests for "add this metric to the dashboard." The data is already accessible.
Three AI providers serve different roles. Gemini 2.0 Flash handles SQL generation (low latency, structured output). Anthropic Claude powers the workflow copilot (complex reasoning, multi-step generation). OpenAI drives campaign content generation. Each model is chosen for the task it's best at, and no single provider is a critical dependency.
Every Redis operation is wrapped in availability checks and try-catch blocks. If Upstash is unreachable, the app falls through to direct database queries. Users experience slower responses, never errors. Rate limiting bypasses rather than blocks. A deliberate trade-off: availability over strict rate enforcement.
Product creation never waits for SimpleRFID. A sync queue decouples the systems — products are queued on create/update and processed asynchronously every 5 minutes. Failed syncs retry with logged errors. An RFID service outage has zero impact on the core product management workflow.
Traditional email/password login doesn't work when four staff share a counter tablet. PIN-based login with bcrypt hashing, 30-minute inactivity timeouts, and rate limiting per PIN hash. All PIN comparisons run in parallel via Promise.all() — constant response time regardless of which user matches.
Inbound webhooks write to staging tables, not the business schema. This separates ingestion from processing: webhook handlers are fast and never fail due to business logic errors, and raw data is preserved for debugging, replay, and eventual processing on our own terms.
Ask business questions in plain English — AI generates SQL, executes it, and returns formatted answers with charts
Scan physical inventory with RFID hardware and reconcile against database records in minutes
Drag-and-drop automation with AI copilot that generates workflows from natural language
Full profiles with purchase history, interaction timelines, preferences, tags, and wishlists
26+ filter types for dynamic customer segments with cached member counts
AI-generated content, per-recipient tracking, open/click analytics, automated unsubscribe
End-to-end tracking from intake to completion with automated customer notifications
Bidirectional product and customer sync with webhook-driven updates
Repair tickets, invoices, buying-in slips, and cash receipts rendered server-side
ESC/POS print server bridges the cloud PWA to local receipt printers
Cache-aside pattern with tiered TTLs, pattern invalidation, and graceful degradation
Full Progressive Web App — installable on tablets, desktops, and phones with instant updates
Whether you need AI-powered business intelligence, real-time inventory management, or a system that replaces five tools with one — we'd love to talk.
Get in Touch →