The Salon Co.
A 14-page luxury salon website with a full-stack booking engine — 4-step reservation flow, Stripe deposit checkout, real-time stylist availability from Supabase, Resend transactional email, and automated cancellation with a 48-hour refund policy. Owned outright with no monthly platform fee.
The Problem
Most salons are booked through platforms like Square Appointments, GlossGenius, or Vagaro that charge $25–100/month in perpetuity, impose their own branding on every customer-facing page, and in some cases take a cut of each transaction. The UX is generic by design — the same template used across thousands of salons — and the owner never fully controls the experience. The goal was a custom-branded presence built from scratch that feels genuinely luxury: a 4-step reservation flow with per-stylist availability, 25% deposit collection through Stripe, and automated email confirmation and cancellation — all owned outright with no subscription, no platform lock-in, and no commission per booking.
Try It
Previewing at tablet width. Open the full site ↗ for the desktop experience. Also fully optimized for mobile.
You're on mobile — open the full site ↗ for the best experience. Any display issues are caused by the embed, not the site itself.
Meet Your Stylist
Each stylist has a profile card with their photo, specialty, and bio — so clients know who they're booking before they sit down. Builds trust and reduces no-shows from uncertain first-timers.
Stylist Selection
Step two of the booking flow only shows stylists who actually perform the selected service — so clients never see someone who can't help them. Smart filtering at the selection step, not an afterthought at checkout.
Date & Time Selection
Clients pick their appointment date and time from a live availability calendar — slots reflect the selected stylist's actual schedule.
Mobile Experience
Technical Implementation
Booking Flow
Four steps: service selection (radio buttons mapped to valid stylists per service), stylist selection (cards dynamically enabled or disabled based on both service compatibility and per-stylist availability), date and time selection via a fully custom calendar, and a confirmation step where the client enters their details and pays a 25% deposit. The progress bar updates on each step transition with a smooth scroll back to the top of the booking section.
Stripe Checkout & Webhook
When the client submits their details, the front end POSTs to /create-checkout-session, which validates all inputs server-side, pulls the service price from Supabase, calculates a 25% deposit amount, and creates a Stripe Checkout session. When payment completes, Stripe fires a webhook to /webhook — the handler writes the booking to Supabase and sends a confirmation email through Resend. The success page fetches booking details from Supabase first, falling back to Stripe session metadata directly if the webhook hasn't fired yet — handling the race condition between a fast browser redirect and slower webhook delivery.
Cancellation & Refunds
Each booking is issued a UUID cancel token at insert time. The confirmation email carries that token in a link — no login, no account required, and the URL can't be guessed. When a client clicks it, the server calculates time remaining: cancellations at least 48 hours out trigger an automatic Stripe refund executed server-side through the Stripe API; inside 48 hours, cancellation requires calling the salon directly.
Real-Time Availability
The calendar makes two live API calls when a stylist and month are selected: /closed-dates returns owner-blocked dates stored in Supabase, and /booked-dates returns all confirmed bookings grouped by date so fully-booked days can be greyed out. When a specific day is selected, /booked-slots returns the taken time slots for that stylist on that date — the remaining slots render as selectable buttons. An AbortController cancels in-flight slot requests if the client changes their date selection before the previous fetch completes.
Scroll Behavior & UI
A scroll event listener transitions the header to its condensed sticky state once the page scrolls past 10px. The reviews carousel auto-rotates every 3 seconds with clickable progress bar dots that jump to any review directly. The gallery filter uses CSS class toggling to show and hide items by category — no external library. The FAQ accordion manages open/close state with display toggling, defaulting to the first item open on load.
Contact Form
The contact form POSTs to /contact, which sends a formatted email to the salon owner through Resend with a reply-to header pointing at the client's address — the owner can reply directly from their inbox without any intermediary dashboard.
SEO
Schema.org HairSalon JSON-LD structured data on the homepage with address, hours, and contact details. Verified passing in Google's Rich Results Test.
The Outcome
A 14-page luxury salon presence the owner controls outright — no subscription, no commissions, no platform lock-in. Each of the four core services (precision cut, color highlights, blowout, keratin treatment) has its own SEO-optimized page with pricing, description, and a direct booking link. Clients can browse services, see stylist availability in real time, book and pay a deposit through Stripe, and cancel if needed — all from the same site. Designed and built solo. Part of the Small Business Platform Suite.
Need a website for your business? I take on select freelance web projects.
Let's talk →