Baku Heritage Tours

Full-stack development
A tour-booking and operations platform for a heritage-tour operator, built solo. It handles the whole lifecycle: a visitor books a tour online, and staff scan the QR ticket at the gate. Under the hood it's a Next.js Turborepo monorepo with a microservices backend.

The problem

Small tour operators run on a patchwork. A booking form here, a spreadsheet there, paper tickets at the door, and no single view of what's actually happening. Double-bookings slip through, walk-ins are hard to price, and nobody can say who really showed up. Baku Heritage Tours puts all of that in one place. Sell online, check people in at the gate, and see everything from one dashboard, so a small team can run more tours without more overhead.

What it does

Capability
What it means
QR ticketing & check-in
Issue a scannable ticket on booking, and validate it at the door
Reservations & dynamic pricing
Manage availability and adjust prices by demand and season
Content CMS
Staff manage tours, media and pages without a developer
Audit logging
Every sensitive action is recorded for accountability
Scheduled jobs
Reminders, cleanup and reporting run on their own

How it works

A Next.js app serves both the public site and the staff admin. Behind it, a set of Elysia.js services own separate slices of the domain over typed contracts. PostgreSQL (through Prisma) is the source of truth, and Redis handles anything fast and disposable like rate limits, job queues and caching. A booking moves through the system like this:
  1. Book. A visitor picks a tour and slot. The service checks availability and prices it.
  2. Issue. A QR ticket is generated and a confirmation email goes out.
  3. Scan. At the gate, staff scan the QR and the service validates it and checks the visitor in.
  4. Record. The check-in is logged, and scheduled jobs handle reminders and reporting.

Highlights

  • Built solo, end to end: data model, services, UI and deployment
  • Covers the full lifecycle, from booking to payment to ticket to gate scan
  • Microservices on a shared-types monorepo, so client and services never drift
  • Operations kept honest by audit logs and scheduled jobs

Stack

Next.js Next.js · Turborepo Turborepo · Bun Bun · Elysia.js · Prisma Prisma · PostgreSQL PostgreSQL · Redis

Why this stack

Choice
Why
Instead of
Next.js (App Router)
Server components render tour pages fast for SEO, and one framework covers both the public site and the admin
a separate SPA plus a standalone API
Turborepo monorepo
Web and services share types and UI from one install, so the client can't drift from the API
a polyrepo with duplicated, hand-synced types
Elysia.js on Bun
Tiny, end-to-end-typed services with first-class performance
a monolithic Express app with untyped routes
PostgreSQL
Bookings and tickets need relational integrity and hard constraints
a document store like MongoDB
Redis
Fast, disposable state for rate limits, job queues and caching
hammering Postgres for every transient read


Biggest thing I've built solo. A whole business running end to end on one system. Ambitious, sure, but that's exactly why I took it on.