← All case studies

Full-Stack Platform · ISNA 62nd Annual Convention · Oxibit Technologies

Convention Booth Reservation System

An online booth reservation platform built for the Islamic Society of North America's (ISNA) 62nd Annual Convention Bazaar — a guided, seven-step booking flow across an interactive floor plan with real-time hold logic, Stripe payments, and an admin dashboard, replacing a manual phone-and-spreadsheet process.

Role: Full-Stack Developer — Angular Frontend & Node.js Backend

Angular 15Node.jsExpressMySQLSequelizeStripeSocket.io

500+ booths across 5 pricing tiers

Booth inventory

Hold + re-validation prevents double-booking

Concurrency

Stripe Payment Intents with automated refunds

Payments

The Problem

ISNA runs one of the largest Muslim conventions in North America, with a Grand Bazaar where hundreds of vendors reserve exhibition booths. Before this platform, that process relied on manual coordination — phone calls, emails, and spreadsheets — which created double-booking risk, no way to represent complex booth tiers and add-ons, and heavy admin overhead for staff trying to track bookings, refunds, and exports by hand. ISNA needed a self-service web application handling the full vendor journey — from reading the contract to paying and receiving confirmation — under real event-day traffic.

  • High demand, limited inventory — 500+ booths across five pricing tiers, sold on a first-come basis.
  • Double-booking risk — multiple vendors could attempt to reserve the same booth at the same time.
  • Complex offerings — booth tiers (Standard through Sponsorship Aisle), plus optional advertising add-ons.
  • Payment & compliance — vendors had to accept a detailed exhibition contract, pay online, and receive an official confirmation.
  • Admin overhead — staff needed to view bookings, process refunds, and export data without digging through email threads.

The Approach

  • 01Built a guided, seven-step vendor flow: accept the exhibition contract, review the bazaar floor plan, select booths on an interactive map, choose optional advertisements, enter contact details, pay via Stripe, and land on a confirmation page.
  • 02Built an interactive, color-coded floor plan mirroring the physical hall layout, with booths priced across five tiers ($650–$2,200) and live sold/held/available status.
  • 03Implemented a real-time hold system: selecting a booth triggers a server-side availability check and a 10-minute Hold status, with a cron job releasing expired holds and a final re-validation pass before payment.
  • 04Integrated Stripe Payment Intents on both frontend (ngx-stripe) and backend, with atomic database transactions creating the booking, contact record, payment record, and booth assignments together on success.
  • 05Built confirmation and documentation: a confirmation page, an auto-generated PDF (jsPDF + html2canvas), and a transactional email via Handlebars templates and ZeptoMail.
  • 06Built an admin dashboard for authenticated staff to view bookings in a sortable table, export to Excel, edit vendor contact info, and process Stripe refunds that automatically release booths back to inventory.

Key Features

Interactive Booth Floor Plan

  • A visual map of the hall mirrors the physical layout, color-coded by category (Standard $650 through Sponsorship Aisle $2,200), with sold, held, and unavailable booths visually distinct.

Real-Time Availability & Hold System

  • Selecting a booth triggers a server-side check and a 10-minute Hold while checkout completes; a background cron job releases expired holds.
  • All selected booths are re-validated immediately before payment, so a vendor is notified and can pick alternatives if anything was taken in the meantime.

Advertisement Upsells

  • Vendors can add convention advertising — program book print ads, main-hall video ads, banners, website ads, and session-room naming rights — with pricing rolled into the final checkout total.

Stripe Payment Integration

  • Payments run through Stripe Payment Intents on frontend and backend; failures release booth holds automatically, and success creates the booking, contact, payment, and booth assignments in one atomic transaction.

Confirmation & Documentation

  • A confirmation page, an auto-generated PDF (jsPDF + html2canvas), and a transactional email with booking details (Handlebars templates via ZeptoMail).

Admin Dashboard

  • Authenticated admins view all bookings in a sortable DataTable, export to Excel, edit vendor contact information, and process Stripe refunds that automatically release booths back to available inventory.

Technical Highlights

Frontend — Angular 15

  • Multi-step wizard with route-based navigation and a shared EventService (RxJS BehaviorSubject) for booking state across steps.
  • localStorage persistence so selections survive page refreshes during checkout, plus auth guards and HTTP interceptors for protected admin routes.

Backend — Node.js / Express

  • Modular REST API (authentication, events, booths, bookings, advertisements, dashboard) with Sequelize ORM over MySQL and database transactions for booking creation.
  • Joi request validation on all endpoints, AES encryption for IDs in API responses, and a node-cron job releasing booths stuck in Hold status after 10 minutes.

Integrations

  • Stripe for payment intents, card payments, and refunds; ZeptoMail/Nodemailer with Handlebars templates for confirmation and error-notification emails.

Challenges & How I Solved Them

Race conditions on popular booths

A three-layer approach: Hold status on selection, a final multi-booth availability check right before payment, and Sequelize transactions when marking booths as Sold. Failed payments revert booths to Available.

Mapping 500+ booths to a UI

A row-based floor plan component aligned to the real convention center layout, merged with live API data for status and pricing per booth.

Stateful multi-step checkout

Centralized state in EventService plus localStorage for booths, contact info, and advertisements, with a 10-minute session timer that reloads the page if checkout stalls.

Refunds without manual booth tracking

An admin refund action triggers a Stripe refund, updates booking status to Cancel, and sets associated booths back to Available in one flow.

Tech Stack Summary

FrontendAngular 15, TypeScript, Bootstrap 5, RxJS, ngx-stripe, ngx-toastr, DataTables, jsPDF, ng2-pdf-viewer
BackendNode.js, Express, Sequelize, MySQL, JWT, Joi, bcrypt, node-cron, Socket.io
PaymentsStripe (Payment Intents, Refunds)
EmailZeptoMail, Nodemailer, Handlebars
DevOpsHTTPS/SSL support, environment-based config

Have a similar system in mind?