A production-ready booking website for salons, spas, and service businesses. Built with Next.js 15, Tailwind CSS v4, and the Opencals Storefront SDK.
Sign up at app.opencals.com and create a Dev Store. When prompted for a dataset, choose "HAAR Salon" — this seeds your store with sample services, staff, and locations so your template looks exactly like the demo.
Go to your User Account Settings in the Opencals dashboard and generate a Storefront API key. You'll need this to connect the template to your store.
During deployment, Vercel will ask you to set environment variables:
| Variable | Value |
|---|---|
OPENCALS_API_KEY |
Your Storefront API key (starts with sfk_) |
AUTH_SECRET |
Any random string — used for session encryption |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
(optional) Your Stripe publishable key for payments |
That's it. Once deployed, you'll have the same fully functional booking site as the live demo.
A magazine-style salon site: Bodoni Moda headlines, numbered sections, plate captions and arch-masked photography taken from the salon's arched mirror. Motion (line-masked reveals, arch wipes, a pinned "Ritual" sequence, Lenis smooth scroll) lives in components/motion/ and switches off under prefers-reduced-motion.
One page instead of a wizard. Numbered sections (service, stylist, day & time, finishing touches) unlock in order, while a live appointment card writes itself in on the right. In "Any stylist" mode each time slot shows who is free, and you pick your stylist right there. Reserving flips the card to "Held for you" with the hold countdown. Closed days are greyed out, and ?date=&staff=&location= deep links pre-fill the composer.
Variants show as "Hair length" choices (Short / Medium / Long), each with its own price, duration and staff. The location selector filters the menu, the stylists and the availability.
Your details → a few questions → payment, next to a stack of appointment cards with discounts, tax and a hold timer you can extend. Supports Stripe (card, Apple Pay, Google Pay), pay at the salon, bank transfer and free bookings.
The card comes back stamped "Confirmed", with add-to-calendar (.ics + Google Calendar), directions and a "Before your visit" checklist.
Sign in with a 6-digit email code or a password; links from booking emails sign the customer straight in. "Your salon diary" shows the next visit with a countdown, past and upcoming appointments, orders as receipts, and reschedule / cancel where the store allows it.
On phones the appointment card becomes a sticky "Your card · $80" bar that opens as a sheet, and checkout gets a sticky pay bar.
Per-page metadata, Open Graph/Twitter cards, JSON-LD structured data, robots.txt, and sitemap.xml — all configured out of the box.
| Category | Technology |
|---|---|
| Framework | Next.js 15 (App Router) |
| Styling | Tailwind CSS v4 |
| Animations | Framer Motion |
| Forms | react-hook-form + Zod |
| Payments | Stripe Elements (Payment Element) |
| Auth | NextAuth.js v5 |
| Dates | moment-timezone |
| API | Opencals Storefront SDK |
git clone <repository-url>
cd haar-salon-template
npm install
cp .env.example .envEdit .env with your values:
OPENCALS_API_KEY=sfk_your_key_here
AUTH_SECRET=change_me_to_a_random_string
npm run devOpen http://localhost:3000.
All salon-specific copy is centralized in lib/site-config.ts:
- Salon name, tagline, and logo
- Homepage hero text, CTA sections, and testimonials
- About page story, team members, and values
- Contact information (address, phone, email, hours)
- Footer links and social media
Edit this single file to rebrand the entire template.
Colors are defined as CSS custom properties in app/globals.css:
@theme {
--color-accent: #E8530E; /* Primary brand color */
--color-cream: #F5F0EB; /* Light background */
--color-charcoal: #1A1A1A; /* Dark text/backgrounds */
--color-warm-gray: #8A8279; /* Secondary text */
--font-display: 'Playfair Display', Georgia, serif;
--font-body: 'Inter', system-ui, sans-serif;
}Follow the existing pattern:
- Create
app/your-page/page.tsx(component) - Create
app/your-page/layout.tsx(metadata) - Add to
navLinksincomponents/layout/header.tsx
app/
page.tsx # Homepage
services/page.tsx # Service listing with location filter
booking/[slug]/page.tsx # Booking page (date/time/staff picker)
checkout/page.tsx # Multi-step checkout
thank-you/page.tsx # Post-checkout confirmation
about/page.tsx # About page (story, values, team)
contact/page.tsx # Contact form + info
account/ # Customer dashboard (appointments, orders, settings)
auth/ # Sign in, sign up, forgot/reset password
api/ # API routes (products, availability, booking, checkout, auth)
components/
layout/header.tsx # Fixed header with nav, auth, cart
layout/footer.tsx # Footer with location/timezone selectors
home/ # Homepage sections (hero, CTA, gallery, testimonials)
booking/ # Date picker, time slots, staff/location selectors
cart/cart-drawer.tsx # Slide-out cart drawer
checkout/ # Step components (customer, questions, payment, summary)
ui/ # Shared UI components (form, staff-avatars)
contexts/
cart-context.tsx # Cart state + localStorage persistence
checkout-context.tsx # Checkout multi-step state machine
location-context.tsx # Global location selector
timezone-context.tsx # User timezone detection + override
hooks/
use-api-request.ts # Generic fetch wrapper with loading/error
use-form-submit.ts # Form submission with API call
use-date-formatter.ts # Timezone-aware date/time formatting
lib/
site-config.ts # All branding, copy, and content in one file
opencals.ts # SDK client setup
schemas.ts # Zod validation schemas
format.ts # Price, duration, image formatting
auth.ts # NextAuth configuration
| Variable | Required | Description |
|---|---|---|
OPENCALS_API_KEY |
Yes | Storefront API key from your Opencals dashboard |
AUTH_SECRET |
Yes | Random string for NextAuth session encryption |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
No | Stripe publishable key for payment processing |
OPENCALS_API_URL |
No | Override API base URL (defaults to production) |
HAAR is one of the open-source booking templates built on the Opencals Storefront SDK. Same backend, different design and vertical:
- Clear Care — a medical clinic template with department-first booking. Live demo
- Frisor — a modern barbershop template with a dark editorial palette. Live demo
- VOLT — a padel & squash club template with a court booking grid. Live demo
- NOIR Drive — a luxury car-rental template (Dubai) with multi-day booking by the day and chauffeur packages. Live demo
- Fluently — a language-school template (New York) with group classes, live seats, private lessons and online lessons. Live demo
See all templates and the Storefront API at opencals.com/developers.
Prefer to let an AI agent do the heavy lifting? Install the Opencals Agent Skills in Claude Code, Cursor, Codex or Gemini CLI:
opencals-build-booking-site— scaffold, wire and deploy a template like this oneopencals-storefront-api— ground-truth reference for the Opencals API & SDK
Docs: opencals.com/docs → AI Agents.
MIT






