khanhanh@sydney: ~/projects/celia-studio-booking · cat celia-studio-booking.md
$ cd .. back to ~/projects (esc)

case-study --deep-read

celia-studio-booking

Booking-led brand site for a Bankstown lash and brow studio

project: celia-studio-bookingrole: full-stack deliverystack: Next.js · Typescript · vercel · Cloudflaretimeline: 2026status: live

Celia Studio is a booking-led website for a lash and brow studio in Bankstown. The business problem was simple: customers needed to understand services, pricing, availability and trust signals before contacting the owner. The engineering problem was making that flow editable, fast and reliable without turning a small business site into a heavy application.

Problem

The site had to do more than look good. It needed to answer the questions a customer asks before booking: What services are available? What do they cost? What does the work look like? Where is the studio? Is there availability? What happens after I submit?

For the owner, the important part was operational: content should be editable, bookings should land in the right calendar, and both the customer and studio should receive clear confirmation.

Architecture

The public site uses the Next.js App Router with server-rendered sections for the main marketing content. Sanity owns editable content: site settings, hero slides, services, portfolio items, testimonials, FAQ groups, service areas and booking service metadata. The app reads that content through one server-only content function with seed-data fallback, so the site can still render if Sanity is unavailable.

The booking flow is a client form backed by server actions. The client manages form state and validation with TanStack Form and Zod. Available time slots are fetched from Cal.com through a server action, then cached client-side with TanStack Query. Creating a booking posts back to Cal.com and sends confirmation emails through Resend.

Key decisions

The first decision was to keep the homepage mostly server-rendered. The booking, portfolio and testimonials areas are lazy-loaded where interactivity or heavier media makes that useful, but the core landing path remains fast and indexable.

The second decision was to put business content in Sanity but keep the booking logic in code. Sanity should own service names, prices, images, testimonials and FAQ copy. It should not own validation rules, date filtering, API versions or error handling around external booking systems.

The third decision was to validate twice. The client validates fields for a good user experience; the server validates the payload again before calling Cal.com. The server also rejects slots that are too close to the current time, because a slot can become invalid while the user is filling out the form.

Hard parts

Time zones were the first challenge. The UI needs to speak in Sydney time, while the API returns concrete timestamps. The slot fetcher requests availability in Australia/Sydney, filters out near-past slots with a small buffer and formats display times consistently.

The second challenge was failure handling. A booking API can reject a time after the UI displayed it. The server action translates that into a useful recovery message: choose another slot. That is a better user experience than a generic form failure.

The third challenge was keeping the site maintainable for a non-technical owner. The content model separates site settings from homepage sections, and the code has a typed fallback path. That means the site has an operational safety net while still letting the owner update services and page content without editing code.

What this demonstrates

Celia Studio shows practical client delivery: CMS modeling, SEO structure, third-party booking integration, server actions, validation, email notifications and production launch details. The technical decisions are quiet on purpose; the business gets a site that sells, books and stays maintainable.

-- EOF · written by khanhanh, edited by nobody● open live ↗next: goat-food-and-tea.md →