Case Study · Custom Web App
Noupoort Mountain Estate
A booking and venue management platform for a 24-cabin wedding estate in the Piketberg mountains. Five interfaces on one platform, replacing phone calls and spreadsheets.
Escape to the mountains, arrive at a working system
Weddings bring up to 150 guests who each need a cabin on a rugged mountainside. Before this platform, the owner tracked 24 cabins in spreadsheets, chased payments through bank statements and coordinated cleaners by text. Now one idea organises everything: cabins are only bookable through an event. The couple shares a code; every booking rolls up to their function with a complete financial picture.
The demos below are working slices in the estate’s own palette. All names, codes and amounts are fictional.
The Booking
One code from the invitation. Four steps. Built for elderly guests on phones: big targets, no accounts, no passwords.
Enter the event code
The homepage booking bar accepts WEBER-MALAN-2026; the event name, couple and dates appear instantly.
Pick from the live grid
Only cabins released for this event show, with photos, capacity and per-night rates. Event dates glow gold on the calendar.
Add the people
Names, age bands, dietary requirements, international phone input. Each cabin can even hold its own check-in and check-out dates.
Review and submit
Per-cabin costs, extras, VAT shown separately, breakage deposit as an informational line, one amber non-smoking notice.
Reference issued
A large monospace reference, invoice download, and the portal link by email with banking details.
The Estate Map
Twenty-four cabins at their true GPS positions on MapLibre, colour-coded by booking, payment and cleaning status. Native GeoJSON layers, because HTML markers drifted and stuttered on phones. Tap a marker.
The Payments
Guests pay by EFT and claim it; the owner confirms in one click and both sides flip green. It replaced a button that faked success and saved nothing. Try the loop.
Guest portal · NPT-0412
Status: No claims yet
Admin · Payment Claims
Confirming updates total paid and flips the booking: UNPAID, PARTIALLY PAID, PAID.
The Invoice
Package tiers, extras, custom items, free-night deductions, deposits and a per-function VAT exemption toggle. One shared line builder feeds the admin invoice and the host proforma, so they can never disagree.
| Description | Qty | Unit | Total |
|---|---|---|---|
| Wedding package · 100 guests · 3 courses | 1 | R98,000.00 | R98,000.00 |
| Friday night menu | 100 | R240.00 | R24,000.00 |
| Conference room | 1 | R10,000.00 | R10,000.00 |
| Loyalty discount · returning client | -R5,000.00 |
The Housekeeping
Four cleaners, phones in the field, patchy signal. An installable PWA with PIN login, 56px targets for gloves, photo breakage reports and checklists that schedule themselves from bookings. Tick the boxes.
The estate’s own palette
Warm golds against slate, a serif voice for the guest-facing pages, tight utilitarian type in the admin. Straight from the platform’s Tailwind config.
The ten-step gold scale, with #a8753b as the working primary · slate #2D3E50 for dark surfaces · guest pages set with serif display headings and an italic gold accent, admin pages in compact sans with 11px uppercase eyebrow labels and pill toggles
Function-gated, not open
The estate is a venue, not a resort. Functions own bookings; that one decision shaped the whole data model.
Passwordless guests
Booking reference plus last 4 phone digits. Wedding guests never create accounts.
EFT with claims, not gateways
Card payments were built, then deliberately disabled. The owner prefers EFT with reconciliation, so claims bridge the gap.
Per-cabin date overrides
Cabin 14 arrives Friday, cabin 15 on Saturday, in the same booking. The model bends to real weddings.
Next.js 14 · TypeScript · Supabase (46+ tables, RLS) · MapLibre GL · FullCalendar · React PDF · Resend · PWA · Vercel · 152-page verified builds · Playwright E2E on production
The screens


“Okay on the bookings for guest, absolute hundred percent, it looks great.”
Jo · Owner, Noupoort Mountain Estate