krishna@
~/projects
liveproduct · 2025 →

Next Trekking

Booking the Himalayas, properly.

Next Trekking — preview
01 // overview

Trekking and expedition booking platform for Nepal — public web app, iOS and Android app, and an operations console over a booking engine that handles multi-traveller trips, capacity, cancellation policy and refunds. I led the project and the team of eight that built it: four codebases, 165K+ lines, shipped in under a year.

02 // the.story

the problem

Nepal sells the Himalayas, and it mostly sells them over WhatsApp.

The trekking industry here is enormous and almost entirely un-systematised. A traveller in Berlin decides they want to walk to Everest Base Camp, finds an operator through a search result or a friend, and then begins a two-week email thread: is October available, what does the permit cost, does the price include the Lukla flight, what happens if my knee gives out on day nine. Somewhere in that thread money changes hands, often by bank transfer, on trust. The operator tracks the whole thing in a spreadsheet and their own memory.

That works, in the sense that it has worked for decades. But it loses bookings constantly — to the operator who replied first, to the one whose website answered the question without an email, to the one who looked like a real company at 2am in a different timezone. And it puts the traveller in the uncomfortable position of wiring several thousand dollars to a stranger with no confirmation, no itinerary of record, and no stated policy on what happens if plans change.

Next Trekking is that business rebuilt as software: browse, compare, see the real itinerary and the real inclusions, book with the people you're actually travelling with, pay by card, and have a policy in writing before you go.

what it is

Four surfaces over one platform:

  • A public web app — the trek catalogue with itineraries, maps, inclusions and exclusions, difficulty, departures and pricing, plus reviews, blog content and the full booking and payment flow.
  • A mobile app on iOS and Android — browsing, bookmarks, bookings and trip management in your pocket, which matters when you're already in Kathmandu.
  • An operations console — the tool the company actually runs on: catalogue management, departures and availability, bookings, cancellations, refunds, add-on orders, content, users and roles.
  • A backend holding the domain: catalogue, availability, bookings, payments, policy, notifications and the reporting behind all of it.

Four codebases, 165K+ lines, and the whole thing went from empty repository to shipped product in under a year.

my role

I led the project and I ran the team. Concretely:

I owned the backend. Data model, API, booking engine, payments, auth and permissions, jobs, real-time, and the deployment. It is the piece everything else depends on and it was mine.

I was the largest contributor to the mobile app, building alongside a mobile developer who took day-to-day feature delivery.

I built the web app and the operations console with a front-end group — several developers of varying experience, where my job was the architecture, the API contracts, the conventions and the review rather than the majority of the components.

Where Joishi was mostly a depth problem — one person, one enormous engine — this was a breadth problem. Eight people contributed across four repositories in under a year, and most of the difficulty was in making that many hands produce one coherent product.

the hard part: a booking is not a shopping cart

It is tempting to look at this and see e-commerce. Add trek to cart, pay, done. That model breaks almost immediately, and understanding why is most of the engineering.

A booking is for people, not quantities. Four travellers on one trek are not "quantity: 4". Each one has a name, passport details, dietary requirements, emergency contacts, an insurance policy and possibly a different arrival date. The booking is a container of people, each with their own record, and any one of them can change or drop out without destroying the trip.

Availability is not stock. A departure has a date, a capacity, a guide, and blackout windows. It cannot be oversold, and two people booking the last two places at the same moment is a race that has to be resolved correctly at the database level rather than hopefully in application code.

Cancellation is a first-class domain object. A trek cancelled ninety days out and one cancelled nine days out are completely different events financially, and the traveller must be able to read that rule before paying. So policy is modelled data — attached to the trek, versioned with the booking, and applied by the system when a cancellation happens. Refunds are computed from it, not negotiated over email.

The trip continues after payment. Bookings get updates, itineraries change, treks need gear the traveller doesn't own, and everyone needs a packing list they can tick off. There is a whole add-on commerce flow — equipment and services ordered against an existing booking — with its own catalogue, orders and fulfilment states, and it has to stay coupled to the trip without becoming a second shopping cart bolted onto the first.

Trust has to be visible. Reviews, real photography, complete itineraries, explicit inclusions and exclusions, and email that arrives when it should. None of that is technically hard. All of it is why somebody in Berlin puts $1,299 on a card for a company they have never met.

Around fifty-odd domain models and roughly 230 endpoints later, that shape is what the backend encodes.

running a team of eight

This is the part I would want to be judged on. Eight contributors, four repositories, mixed experience levels, under a year, one product that behaves like one product.

Contracts before code. Every feature started as an agreed API shape. The web, admin and mobile developers could all build against it in parallel while I implemented the real thing, which is the only way a small team ships four surfaces at once.

The backend as the single source of truth. No client re-derives business rules. Pricing, cancellation charges, availability and permissions are computed server-side and handed to the clients as answers. Three front ends independently implementing a refund policy is three subtly different refund policies, and the one your customer quotes back to you is always the wrong one.

Review as the teaching surface. Several of the developers were early in their careers. Every review comment carried a reason, because the goal was never to land the patch — it was that the next patch wouldn't need the comment.

Shared conventions over individual preference. Same project structure, same state approach, same commit rules, same release process across the repositories. Personal style is a luxury a small team shipping fast cannot afford, and consistency is what let me review everything without holding four different mental models.

Unblocking as the priority. When you are the lead and the backend owner, your own throughput is not the bottleneck that matters — theirs is. I answered questions before I wrote code, and shipped endpoints in the order the clients needed them rather than the order I found interesting.

shipping it

I own the infrastructure and the release process here too.

Deployment is release-driven: cutting a GitHub release triggers a pipeline on a self-hosted runner that installs, injects environment configuration from encrypted secrets, builds, and hands the process to a supervisor that keeps it alive and restarts it on failure. nginx sits in front as the reverse proxy. The web app, the console and the API each ship on the same pattern, so there is exactly one deployment story to know rather than three.

Behind that: MySQL for the domain, Redis for sessions, caching and queues, background jobs for email and notifications, scheduled tasks for the recurring work, structured rotating logs, rate limiting and the usual security headers, plus automated database backups — because the thing that ends a booking company is not downtime, it is losing the bookings.

the stack, in shape

  • Backend: Node and TypeScript on Express, Sequelize over MySQL, Redis for sessions, cache and queues, Socket.IO for real-time, JWT and Google sign-in, Stripe for payments, Firebase for push, templated transactional email, and generated API docs.
  • Web and console: Next.js with React and typed state, sharing conventions and a permissions model that mirrors the backend's.
  • Mobile: Flutter on iOS and Android with offline-capable local storage, push, in-app payment and social sign-in.
  • Infrastructure: self-hosted CI/CD from GitHub releases, process supervision, nginx, and scheduled backups.

what stays with me

Model the domain, not the transaction. Every hard decision on this project came back to refusing to treat a trek booking as a purchase. Once travellers, departures and policy were first-class things rather than fields on an order, most of the feature requests that followed had obvious answers.

A lead's real output is other people's throughput. My commit count is not the interesting number here. Eight people shipping four coherent surfaces in under a year is, and that came from contracts, conventions and review — not from me writing more code than anyone else.

Put the rules in one place and make everything ask. Three clients and one set of business rules is only survivable if the rules live server-side and the clients are told the answer. Everything I would defend about this architecture follows from that one decision.

The site is live at nexttrekking.com, and the app is on both stores.