TL;DR — A salon owner in Casablanca got booked at 3am her local time by a London consultant who thought she was booking 3pm. The booking row was correct (timestamptz, stored in UTC). The display layer wasn't. Three weeks later I figured out you can't model "time" as one thing in a booking app — you need two: the wall-clock time the seller advertises ("I'm open Mon-Fri 9-17") and the absolute moment the booking happens. Mixing them is the bug that broke our salon booking page, our consulting booking page, and three of our paying customers in the same week. This is what I learned.
Stack: Next.js 16, Supabase Postgres, Intl.DateTimeFormat (no luxon, no moment), React Email + Resend for the confirmation emails.
This is the third post in my build-in-public series on PageStrike. Last week I wrote about the multi-domain proxy.ts that lets one Next.js codebase serve four very different audiences. The week before, I wrote about modeling 6 conversion modes as a discriminated union. Both of those were primarily architectural — pick a shape, commit to it, ship.
This post is different. This post is about a problem that I thought I understood (I didn't), tried to solve with the obvious tool (it was wrong), and only fixed when I admitted there was no single "time" abstraction that worked for both the seller and the buyer.








