An event and experience marketplace for Oman: vendors list events and experiences, sell tiered tickets, and run QR check-in on event day, while customers discover, book, and pay in OMR across a Next.js web app and a native mobile app.
Problem
Local event and experience organisers in Oman had no single, market-fit platform to sell tickets and run the door. Listing inventory, taking OMR payment, issuing tickets, and validating attendees at the gate were spread across generic tools and manual lists — and nothing handled Arabic-first listings, a local payment gateway, or a trustworthy check-in that survives a flaky venue connection.
Approach
We built MyTicket as a two-sided marketplace in a Turborepo monorepo: a Next.js 16 customer web app, a self-serve vendor portal, and a native Expo/React Native mobile app, all over one Drizzle + Neon Postgres backend with Better Auth (organization plugin) separating customers, vendors, and admins. Vendors create event/experience products with tiered ticket types, fixed-date availability slots with real capacity, custom booking and per-attendee forms, refund policies, payouts, and analytics. Checkout is a guided wizard with a 15-minute inventory hold so tickets aren't double-sold while a payment is in flight. Payment runs through AmwalPay (Oman) with HMAC-SHA256 request signing and a webhook-authoritative reconciliation path that is idempotent — a repeated provider callback is detected by system reference and never double-confirms a booking. Every paid booking explodes into individual tickets, each with a unique QR code and a valid → used → expired lifecycle. The vendor scanner validates tickets at the gate and distinguishes success from already-scanned, invalid, expired, cancelled, and wrong-vendor, writing every scan to an audit log; an offline scan queue persists to local storage and batch-syncs with retry when connectivity returns, so the door keeps moving even with no signal. Confirmations go out by email with an ICS calendar attachment.
Outcome
MyTicket is live in production in Oman on a live AmwalPay merchant account, settling ticket sales in OMR. Vendors run the full lifecycle themselves — list, sell, validate at the gate, reconcile, and get paid out — from the portal, while customers buy on either web or the native iOS/Android app. The QR check-in holds up at the door whether or not the venue has a stable connection, and payment reconciliation is webhook-authoritative so a confirmed booking is confirmed exactly once.