SS1WORK

Namib Horizons

A small safari company that does not exist, with a booking system that does. Seats are counted live, held for 15 minutes and sold without ever being sold twice.

CLIENT
FICTIONAL SAFARI OPERATOR
PROBLEM
TWO PEOPLE BOOK THE LAST SEAT
ROUTE
HOLD, THEN ONE ATOMIC BOOKING
RESULT
LIVE RACE: NO SEAT SOLD TWICE
The Namib Horizons demo's home page, as a screenshot
Role
Design and build
Year
2026
Client
Fictional (a made-up safari operator)
Stack
React, Vite, Netlify Functions, Netlify Blobs, zod, Playwright

What this is

Namib Horizons runs guided and self-drive tours of Namibia from Windhoek, from three days on the dunes to fourteen days end to end. The business is made up. What it proves is the hard part of a booking site for a small operator, which is that seats are limited and price depends on the date, the party and the season. A visitor sees live seats left for every departure, gets a price that changes as they choose, holds seats for 15 minutes, and books with a reference, a printable itinerary and a calendar file. The back office changes what the public sees. A visitor can also save tours and design their own route across the map, with the price and a day-by-day draft building as they choose, and send it as an enquiry that shows up in the back office.

Try this

  1. Find a 4 day Etosha tour and hold seats on a date
  2. Pay with the test card and book it, then download the calendar file
  3. Open the back office (passcode shown there) and cancel your booking, then watch the seats come back

How it works

Following one booking from click to confirmation

BrowserNetlify CDNFunctionsSeed dataBlobs storeNightly reset
  1. You choose a tour and a date

    The page asks for the tour's departures. Dates are not stored anywhere. They are worked out from each tour's schedule, so the next twelve months are always there. Seats left come from your own private copy of the bookings.

  2. The price is worked out twice

    The browser prices the trip as you change the party or the extras, so the answer is instant. The server prices it again with the same function when you hold seats, and only its answer counts. Season, group discount, single room supplement, children's rate and extras all go through that one function.

  3. You hold the seats for 15 minutes

    The server checks the seats and records the hold in one step, so nobody else can take them while you fill in your details. The countdown you see is corrected for any difference between your clock and the server's.

  4. You pay with a test card and confirm

    The card form is checked in your browser and the digits are never sent anywhere. Confirming sends only your traveller details and the hold.

  5. The hold becomes a booking

    The seats move from held to sold in one atomic update, and the booking gets a reference like NH-ABC234. A second click on Confirm returns the same booking instead of making another.

  6. You get your itinerary

    A page you can print, and a calendar file for the trip. Look it up later with the reference and your surname.

Real versus mocked

What is real and what is mocked in this demo
PartStatusDetail
Seats and availabilityRealSeats left are counted from the schedule, held seats and sold seats. A hold that runs out frees its seats.
PricingRealSeason, group discount, single supplement, children's rate and extras, covered by unit tests that check every line adds up.
Booking without oversellingRealOne compare-and-swap decides who gets the last seat. Tested with 25 requests at once and with two real browsers. On the live site, 15 parallel two-seat holds for the last 8 seats: 4 won, the rest were refused or rate limited, and 0 seats were left.
Back officeRealCancelling a booking frees its seats. Changing capacity or hiding a tour changes the public pages. Changes affect your own copy only.
Custom trip planner and saved toursRealThe planner prices a route with one tested function and the enquiry is validated, rate limited and stored in your own copy. Saved tours live in your session. Nothing is booked or held from the planner.
ToursMockedInvented. No real lodges, people or trademarks.
PaymentMockedA test-card form. The digits stay in your browser and nothing is charged.
Email and SMSMockedNothing is ever sent, not even the waiting list.

Data and privacy

Namib Horizons is fictional, so use made-up names and details. What you enter lives in your own private copy of the demo, which no other visitor can see, for up to 24 hours. A nightly job at 02:00 Windhoek time clears it. Nothing is charged, nothing is sent, and no passport details are collected. If your browser blocks storage, the demo still works but forgets you when you close the tab.

Under the hood

Initial JS
130 KB gzipped, React, Router and the motion code included (the budget is 150 KB). Fonts load separately. Measured on the live site.
Lighthouse
Live site, mobile, three runs: Performance 79 to 82, Accessibility 100, Best Practices 93, SEO 92.
  • demos/horizons/src/lib/pricing.js Every price rule in one pure function.
  • demos/horizons/src/lib/inventory.js Holds, booking and cancelling seats, as pure functions on one record.
  • packages/demo-kit/src/store.js The store and its atomic update, shared by every demo.
  • demos/horizons/netlify/functions/book.mjs Turning a hold into a booking exactly once.

What I would do differently

Seat counts are per visitor, so the only contention a visitor can create is themselves against themselves, in two tabs. That makes the no-overselling rule easy to show and easy to doubt. For a real operator the first test would be two strangers, and I would run the race on the live store before writing any of this up, not after.

More demos

  • Ember & SaltA restaurant that does not exist, with a reservation system that does. It only offers tables that are really free, and a service board that runs the night.
  • Kalahari ThreadsA clothing label that does not exist, with a shop that tells the truth. The bag is checked against the real shelf every time it opens, and an order is taken whole or not at all.

All work