Role & scope
Fully designed and built, and developed continuously ever since: a multi-tenant PIM platform with tenant isolation (super admin, tenant admin, tenant user), a draft/publish workflow so every change is reviewed before it goes live, and full audit logging with before/after snapshots.
- Shopify-first synchronisation, alongside a NetSuite ERP integration and export to Amazon and other marketplaces via ChannelEngine.
- AI enrichment of titles, descriptions, SEO copy and translations — with a review step before generated content is published.
- A built-in RAG assistant that lets the product team search and work in the catalogue through chat: vector search over product data, with tool calls for actions the user has to approve first.
- A separate Chrome extension that lets the team drop products from marketplace pages straight into the enrichment queue.
- An EU GPSR compliance module, an SEO module with keyword-volume validation, and background tasks (vector sync, enrichment, scheduler) through a queue with retries.
Impact
- Over 3,400 active products in the core market, with export flows to hundreds of additional listings on marketplaces such as Amazon.
- An AI translation pipeline that silently overwrote category URLs was rolled back and replaced with a version that creates redirects and records everything in an audit trail.
- A sync bug where every NetSuite link overwrote AI content and Shopify changes was fixed structurally instead of being repaired by hand each time.
- Over 350 commits across eight months of continuous development — not a one-off delivery but a system that grows with the assortment.
Architecture
A Turborepo monorepo with a NestJS backend and a Next.js 14 (App Router) frontend, a shared Prisma database package and shared types. PostgreSQL with the pgvector extension stores both product data and embeddings, so vector search and regular queries run on the same database. Background work (vector sync, AI enrichment, marketplace sync) runs through Redis-backed queues with automatic retries and exponential backoff, decoupled from the user interface so a slow marketplace sync doesn't block the rest of the platform.
Model choice
The built-in RAG assistant is deliberately multi-provider: different tasks run through different models (from a cheap model for routine chat to heavier Claude and GPT variants for more complex enrichment work), with per-model token pricing tracked so cost per conversation is visible instead of a black box. Generated content (titles, descriptions, translations) always goes through a review step first — the model proposes, a human approves, the same reason pricing logic in other projects never runs straight through a language model either.
Cost & latency
- Per-conversation token costs are tracked per model, so pricier models get used deliberately and visibly rather than by default.
- Background tasks (vector sync, enrichment) run asynchronously with a maximum of 3 retries and exponential backoff, so a temporary marketplace outage doesn't immediately cause data loss.
- Vector search and regular product queries run on the same PostgreSQL instance (pgvector), which makes a separate vector database and its sync layer unnecessary.
Lessons learned
The AI translation pipeline overwrote category URLs without warning as soon as a translation was regenerated — good for SEO on the face of it, but it broke existing external links. Solved by restoring the historical URLs, adding redirects and building an audit trail that makes such changes visible before they go live. A second bug: every NetSuite sync overwrote AI-generated content and Shopify changes as soon as a product was linked to NetSuite — not an incident but a structural pattern, fixed by revisiting the sync direction instead of repairing it by hand every time. And a third, smaller but telling one: the translation pipeline mistranslated material abbreviations such as "RVS" (stainless steel), fixed with an explicit glossary rule instead of trusting the model to guess domain knowledge.