Engineering

How it’s built

A production ticketing and marketplace platform. Here is what it runs on, how it is tested, and what was measured along the way.

See every feature

Stack

Boring, dependable tools

  • Next.js 15 (App Router)Server-rendered pages, so a listing loads fast on a phone and reads well to Google.
  • React 19 + TypeScriptStrict types end to end; `tsc --noEmit` is part of every change.
  • SQLite via better-sqlite3One file, synchronous transactions — overselling is blocked atomically, backups are a file copy.
  • sharpEvery photo is re-encoded and cut to the exact shape of each slot it appears in.
  • nodemailer over SMTP (SendGrid)Tickets, payment instructions, reminders and security alerts.
  • PayPal & Stripe REST, plain fetchNo SDKs — small clients calling each seller’s own account directly.
  • qrcodeQR tickets, collection codes, GiroCode payment QR and the WhatsApp poster.
  • Gemini + ClaudeVisitor Q&A, the help bot, the AI page designer and voice input — each with fallbacks.

Eight runtime dependencies in total. No ORM, no payment SDKs, no CSS framework.

Architecture

One machine for events and shops

A ticket and a plate of momo are the same thing to this system: a listing (a page), priced types with caps (tiers or items), orders, a QR code per unit and one scan to use it. Events and shops share every line of that — only the words change.

  • Multi-tenant. Every portal and API request checks that the organizer owns the event, order or photo it touches — enforced on the server, covered by tenancy tests.
  • Money never touches the platform. Each seller connects their own IBAN, PayPal or Stripe; buyers pay them directly. The platform is software, not a payment service.
  • Server-side truth. Prices, caps and seats are enforced inside a database transaction, so a browser cannot change a price and a rush cannot oversell.

Reliability & testing

446 tests, and a check that they bite

446

automated tests on Node’s built-in test runner, all passing: money maths, orders and capacity, payouts, promos and referrals, reviews, tenancy, consent, email, SEO.

14 / 19

A mutation audit injected 19 deliberate bugs into the code; the suite caught 14. Each of the 5 that slipped through then got its own test.

Performance

Measured before and after

WhatBeforeAfter
Homepage — SQL statements per request969
Phone homepage — autoplay video downloaded on load10.5 MB0 bytes
Item page — image weight592 KB117 KB
Returning-buyer query (was quadratic)1,026 ms5 ms
Portal dashboard, 20 events — SQL statements2434
Monthly statement — SQL statements1,9883

Security

Built for other people’s money

  • Two-factor sign-in for organizers: an authenticator app, or a code emailed to the account’s own address.
  • Changing where money lands asks the organizer to prove it is them again, takes effect only after 24 hours, and sends an alarm email.
  • Sellers’ own PayPal secrets and Stripe keys are encrypted at rest (AES-256-GCM).
  • Rate limits on sign-in, code checks and order creation.
  • Uploads are checked by their real bytes (magic numbers), not their file name — an SVG disguised as a PNG is refused.
  • Request bodies are capped while they stream in, so an oversized POST is cut off before it is buffered.
  • Door scanner links are signed and time-limited, and open one event’s check-in and nothing else.
  • A tenant-isolation review of every portal route: 9 findings, all fixed, with tests that keep them fixed.
  • A live-exploitable leak of account data on order pages was found and closed with signed per-order access tokens.

Privacy & compliance

Keeps less, for less time

  • GDPR retention: buyer names and emails are overwritten after the event; counts and revenue survive, the person does not.
  • Erasure on request, including customer cards and marketing consent.
  • Marketing is double opt-in only, and every announcement has a one-click unsubscribe.
  • A consent banner is answered before any analytics loads — and analytics never runs on pages whose URL carries a credential.
  • Listing pages name the organizer or shop as the one selling (“Presented by”, “Sold by”), so the seller of record is clear under German VAT rules.

Read the privacy notice →

AI

Helpful, and allowed to say “I don’t know”

  • Grounded: the event assistant answers only from the organizer’s own page content.
  • Strict JSON out, validated before use — a malformed reply is treated as no reply.
  • A confidence gate: when the model is not sure, the question goes to the organizer instead of being guessed.
  • A model ladder with fallbacks (Gemini, then Claude), and built-in answers when no model is reachable.
  • The page designer can only choose from the site’s fixed design options — it never writes code or styles into a page.

Want something like this for your restaurant, shop or events?

Tell us what you run and what gets in the way. A real person reads every message.

Get in touch →
How it’s built | MartNepali