Skip to content
Aadil Salman Butt
← All work
Case study 01

Client buildLive

Junket Tours

A tour booking and operations platform for adventure travel in Pakistan. Guests book without an account, staff run everything from one realtime admin panel, and an AI planner suggests trips from the live catalog.

Junket Tours homepage with featured northern Pakistan tours
Role
Design, frontend, backend and deployment
Timeline
Apr 2026 to now
Stack
Next.js 14, Convex, Groq, Resend, Tailwind CSS
Scale
62 commits

The problem

Junket Tours sells guided trips across Pakistan. The agency needed one place to publish its tours, take bookings and answer trip questions, run by a small team.

The build had two hard requirements. A visitor must be able to book without signing up, and staff must see a booking the moment it lands.

What I built

A tour page with the guest booking form

01

Booking without an account

A guest picks a tour and books with one form. Convex actions send the confirmation through Resend and notify staff of each new booking. Customers who do sign up get a dashboard of their trips.

The tours catalog that staff manage from the admin panel

02

A realtime admin panel

Staff manage tours, destinations, bookings, users and blog posts in one place. The panel reads from Convex subscriptions, so a new booking appears without a refresh.

The AI trip planner form filled in for a 7-day northern trip on a mid budget

03

An AI planner that stays in the catalog

The planner runs as a Convex action that calls Groq with the current tour catalog, so it suggests trips the agency actually sells. A request the catalog can't cover is flagged as a custom plan for staff to price.

How it fits together

One Next.js app and one Convex deployment. There is no separate API server to host.

  1. Browserguests, customers, staff
  2. Next.js 14 on Vercelsite, dashboard, admin, session cookie
  3. Convexdatabase, functions, live subscriptions
  4. GroqAI trip planner
  5. Resendbooking emails

Decisions and trade-offs

Convex instead of a REST API and Postgres

The admin panel has to update live. Convex gives the database, server functions and subscriptions in one deployment, so there is no polling and no second service to run.

Trade-off: no SQL for ad hoc reporting, and the backend is tied to one vendor.

My own session auth

Sessions live in an HTTP-only cookie. Only a hash of the token is stored, in a Convex sessions table, so a leaked table cannot be replayed.

Why not a hosted provider: guests, customers and staff roles all live next to the bookings in one database, with no extra service or per-user bill.

A planner that cannot invent tours

The model gets the live catalog with every request and must answer with catalog slugs. A made-up itinerary would be a sales problem, so the catalog is the only source.

Trade-off: trips outside the catalog become a custom-plan request that a person prices.

Results

62
commits from first scaffold to the live site
5
areas run from one admin panel: tours, destinations, bookings, users, blog
0
accounts needed to book a tour
Next case studyDentalAI Receptionist