Building a Booking System with Next.js
Lessons from shipping salon and tour booking platforms — forms, payments, admin flows, and keeping UX simple.
Booking flows look simple on the surface: pick a date, pick a slot, pay, done. In practice, they touch authentication, inventory, payments, notifications, and admin dashboards.
I've shipped this pattern on Zio Hair (salon appointments + e-commerce) and Tiem Tour (tour search, filters, and custom requests).
Core user flow
- Browse services or tours
- Filter by date, time, stylist, or destination
- Add to cart or book directly
- Pay via OnePay or Megapay
- Receive confirmation (email / admin notification)
The goal is zero confusion between steps. Every screen should answer: where am I, what did I pick, and what's next?
Frontend architecture
// Simplified booking state
const [step, setStep] = useState<"browse" | "details" | "payment">("browse")
const [selection, setSelection] = useState<BookingSelection | null>(null)I typically use Zustand for multi-step booking state — lighter than Redux for form-heavy flows, but still easy to debug.
Admin side matters too
Clients need to manage appointments, update availability, and handle cancellations. WordPress admin + custom post types often handle this, while Next.js serves the customer-facing UI.
What I learned
- Validate early: disable invalid dates/times before the user reaches payment
- Show loading states on payment redirects — users panic on blank screens
- Log booking failures server-side; "payment failed" without context is useless
- Mobile-first: most booking traffic is on phones
A good booking system feels boring in the best way — predictable, fast, and trustworthy.