SYS-01 In production

Retail operations platform

A self-hosted omnichannel platform running customer service and content operations for English Home Libya — catalog-true answers, photo recognition, reliable publishing, and human handoff.

Role
Solo — architecture, implementation, deployment, operations
Timeframe
2025 – present
Stack
TypeScript · Next.js · PostgreSQL · Kysely · Docker Compose · Caddy · Gemini API · Meta Graph API
Links
FIG 01.0 Architecture diagram The production deployment architecture from the repository — one self-managed VPS under Docker Compose (placeholder domains).

Recruiter summary

Problem
A retail brand needs one reliable system for Arabic product questions, image-based identification, catalog pricing, social publishing, and human takeover across Facebook and Instagram.
Contribution
Designed, built, deployed, and operate the platform solo — message ingestion, matching engines, bilingual admin console, Content Studio, durable worker, and self-hosted infrastructure.
Result
Live for English Home Libya: catalog-true answers, exactly-once publishing controls, safety guards grounded in real incidents, and immediate human handoff when intent becomes commercial.

OPS-FLOW

Interactive visualization · drag to inspect

3D ENGINEERING VIEW

The system as an interactive composition

Conceptual 3D operations flow: social channels, durable intake, catalog resolution, transactional delivery, and human handoff.

Use the left and right arrow keys to rotate the scene. A complete text description is provided; no factual claim depends on the visualization alone.

The request path — from Meta channel to human handoff

A linear diagram of eight nodes representing the processing sequence from message receipt to human handoff.

  1. A customer messages through Messenger or Instagram Direct — usually “how much is this?” with a photo. It arrives over a Meta webhook.

  2. Events are persisted as resumable PostgreSQL-backed jobs before processing, while deduplication keys prevent the same webhook from being handled twice.

  3. Prices are read only from the live catalog — more than 4,700 products as of July 2026 — and a price is never invented.

  4. Photo recognition follows the never-guess rule: an empty candidate pool returns none, and human-confirmed corrections teach the matcher.

  5. The system batches message bursts and composes a reply using catalog tools only, with a send-time ai_enabled re-check — if a human took over mid-generation, the AI reply is dropped.

  6. Tool syntax or internal text can never leak into a customer message.

  7. The send intent is recorded in the same database transaction and delivered by a durable worker; a message is only marked delivered when Meta confirms it.

  8. The moment intent moves to orders, refunds, or complaints, the conversation goes to a human — and automation stands down.

Select a stage to inspect it

The problem

Built and operated for English Home Libya, a retail business serving customers in Libya. Product questions arrive in Libyan Arabic across Facebook Messenger and Instagram Direct, often as a photo with “how much is this?” Answering safely means identifying one item from more than 4,700 catalog products (as of July 2026), publishing content without duplicate sends, and never inventing a price or operational state. My experience running the brand’s digital systems supplied the requirements.

The system

Customers message either channel; the platform persists the signed webhook, batches message bursts, identifies the product by code, trilingual text, or photo, answers with prices read only from the live catalog, and hands the conversation to a human when intent moves to orders, refunds, or complaints. A bilingual, RTL-first operations console covers inbox, analytics, image review, runtime controls, and a Content Studio that prepares and publishes Facebook and Instagram posts and stories.

The webhook returns only after the event is committed. A separate worker claims PostgreSQL-backed jobs and a transactional outbox, making customer replies and social publications resumable without silently duplicating provider sends. Multi-admin sessions, readiness checks, and an audit trail keep the operational state explicit.

The pipeline is fed by two subsystems published as standalone repositories: a resumable catalog scraper (real Chrome over CDP) that assembled an image catalog exceeding 11 GB during the documented catalog build, and a deterministic trilingual matcher that decides which scraped Turkish product is the same physical item as a priced Arabic/English catalog entry — only high-confidence matches attach automatically; everything else queues for human review. Photo recognition follows the same “never guess” rule: an empty candidate pool returns none, not the least-bad product, and human-confirmed corrections teach the matcher.

Decisions that came from real incidents

Each of these guards exists because something actually went wrong once:

  • Burst batching — customers send five short messages, not one long one; a five-second newest-wins window prevents five separate replies.
  • Supersede guard — a slow model response can’t overwrite a newer conversation state at delivery time.
  • Send-time re-check — if a human takes over mid-generation, the AI reply is dropped, not sent.
  • Output sanitizer — tool syntax can never leak into a customer message.
  • Honest delivery — a message is only marked delivered when the API confirms it.

From free tier to owned infrastructure

The platform originally leaned on a hosted free-tier database — until the provider paused the project and took the system down with it. I migrated everything to a single self-managed VPS: Postgres 16, the Next.js app, worker, and Caddy under Docker Compose, with nightly backups and a written deployment runbook. The repository preserves that work as an ordered, forward-only migration chain with documented backup and restore procedures.

Verification and limits

Unit, integration, and browser tests cover the migration chain, job queue, webhook durability, deduplication, delivery states, catalog rules, authentication, and channel readiness. What I don’t claim: uptime, traffic, conversion, or reach figures — the repository contains no defensible production benchmarks, and this page does not invent any.

Credits

Solo project, built with modern tooling. It runs on Gemini and Meta’s Graph API; everything else — including the matching engines — is in the linked repositories.

Evidence