Skip to content

Case Studies/Maane Meadows

Maane Meadows

React 19, TypeScript, Express 5, SQLite, Socket.IO, Docker

Maane Meadows

A booking platform, not a brochure site

Maane Meadows is an open-stage farmhouse venue. A brochure site was never going to be enough: guests needed to discover experiences, check real availability by date and occasion, reserve a specific time slot without risking a double-booking, upload photos and videos of their own events, and talk to the owner directly.

The owner needed the other half of that - one place to manage bookings, the experience catalogue, slot rules and guest conversations.

There was a commercial constraint too. The platform had to be cheap to run and fully owned: no per-seat SaaS, no managed database bill, no vendor lock-in.

What we built

A slot-based booking engine. Every experience defines its own time slots, each with a per-date capacity. Availability is computed from real bookings — cancelled ones don't count — and shown live in the catalogue as "Available", "2 of 3 slots left" or "Booked for this date". Crucially it is enforced server-side at checkout, so two guests racing the same slot cannot both succeed.

A self-hosted backend. Node.js, Express and TypeScript over SQLite in WAL mode, with JWT cookie authentication behind an admin allow-list, a typed REST API, file uploads, and Socket.IO realtime so bookings, reviews and availability stay in sync across every connected device.

Media the venue actually controls. Cover images, galleries and guest review media - photos and video - are stored on the venue's own server and served directly. No pasting third-party URLs, no external storage account.

Two ways to talk. A rule-based assistant answers plain-language questions against the live catalogue ("weddings under 2 lakh", "what's available on 20 Aug?") and returns deep links, handing off to a human when needed. Alongside it, guest-to-owner chat carries unread badges on both sides.

An admin panel. Confirm and cancel bookings, edit experiences and slot rules, moderate the guest wall, read the contact inbox, and reply to guest chats.

The decisions that mattered

We migrated off a cloud backend-as-a-service to self-hosted Node, Express and SQLite. The managed service was quick to start with, but it owned the data, the running cost and the runtime. Because the frontend's data-access layer was cleanly abstracted, the migration barely touched the page-level code - a well-drawn boundary is what makes a backend swap affordable. The result is zero backend infrastructure cost and full ownership of the data.

We chose Express over a heavier framework. At this scale it kept the port close to one-to-one with the previous backend and the codebase readable, without adding roughly thirty dependencies for no practical gain.

We built a rule-based assistant rather than wiring in an LLM. The domain is small and structured, so a deterministic agent over the live catalogue is instant, costs nothing to run, and cannot invent an answer. If the conversational surface grows, a language model can be dropped in behind the same interface.

We treated slots as real constraints, not UI hints. Capacity is validated in the booking route itself, not merely disabled in the calendar. The server is the source of truth.

Outcome

  • Zero backend infrastructure cost. SQLite on disk, created and seeded on first boot.
  • One command to run, one container to deploy. The entire application - API, uploads, realtime and the built frontend - runs as a single Node process in a single Docker container. No separate web server, no second service.
  • Verified end to end. A live booking immediately reflects in the catalogue's remaining-slot count, in the assistant's availability answer, and in the owner's unread chat badge - across authentication, checkout, slot selection, uploads, chat and admin reply.