A booking form is the easy half
MERIDIAN is a car-rental site I designed and built end to end. The interesting part was never the form — it was making sure two people cannot drive away in the same car.
The problem worth solving
Almost every rental template on the market treats availability as decoration. You pick dates, you pick a car, you submit — and the site happily takes a second booking for the same vehicle on the same days, because nothing ever asked the database.
That failure is invisible in a demo and expensive in production: the customer arrives at the counter and the car is gone. So this was the part I built first, before any styling.
Availability is a range-overlap question
A booking is not a date. It is an interval, and the only question that matters is whether two intervals overlap. There is a clean rule for that: two ranges overlap when each one starts before the other ends. No calendar loops, no day-by-day expansion.
// every car already taken across the requested window
.from("concept_bookings")
.select("car_id")
.lt("pickup_at", requestedReturn) // starts before ours ends
.gt("return_at", requestedPickup) // ends after ours startsIt is worth being exact about the boundaries. Strict comparisons mean a car returned at 10:00 can be collected again at 10:00 — back-to-back rentals are allowed, and only a genuine collision is blocked. Using `lte`/`gte` here would have quietly refused perfectly valid bookings.
Check twice, and let the second check win
The browser already knows which cars are taken — it asks on page load and again whenever the dates change, and greys out the ones that are unavailable. That is a courtesy, not a guarantee. Between the moment the page rendered and the moment the visitor pressed Confirm, somebody else may have taken the car.
So the same overlap query runs again on the server, inside the request that writes the booking. If it finds a clash the API answers 409 and the interface says so plainly, instead of writing a second row and discovering the conflict at the counter.
The index follows from the query, not the other way round: (car_id, pickup_at, return_at). Availability is always asked per car, so car_id has to lead or the index never gets used.
A static site cannot hold a database credential
MERIDIAN is a static page — no framework, no server rendering, three files. That is deliberate: it loads instantly and costs nothing to host. But it means any key shipped with it is public, because its JavaScript is public.
So the site holds no credential at all. Every read and write goes through one endpoint on this domain, which keeps the service-role key server-side. The tables have row-level security on and no policies whatsoever — the anonymous key cannot reach a single row, so customer details cannot leak out of a public bundle even by accident.
No payments, on purpose
It would have been easy to bolt Stripe on and call the demo complete. I did not, and the reason is not technical: a concept site that can accept real money creates a real obligation, and there is no fleet behind it to honour one.
Everything up to payment is genuine, though. A booking is stored, the car is blocked for those dates, and the owner gets a notification with the driver, the window and the extras. The demo stops exactly where honesty requires it to.
The fleet is drawn, not photographed
Eight consistent, same-angle car photographs are surprisingly hard to license. Rather than ship a mismatched gallery, every car is generated from one parametric side profile: roof height, bonnet length, ground clearance, wheel radius and axle positions.
Six body shapes are six sets of numbers, not six hand-drawn outlines. That is why a hatchback and a van look like they came from the same designer, and why adding a ninth car is a one-line change rather than an afternoon in a vector editor.
What is not there
It is a concept, so I would rather name the gaps than let you find them. There is no payment capture, no driving-licence verification, no admin panel — bookings arrive as notifications rather than into a back office. Pricing rules are flat: no seasonal rates, no weekend multipliers, no loyalty tiers.
None of those are hard. They were simply not what the piece was built to prove.
Want the same care on your project?
Tell me what you are building and I will say what it actually needs — including the parts that are usually skipped.
Get in touch →