Slatis

Build a Custom Booking Page

Create a fully custom booking flow using the Slatis API — slot selection, form fields, and confirmation.

Overview

This guide builds a three-step booking flow: pick a slot → fill in attendee details → confirm. We use the SDK on the client side with a public key.

1. Setup

npm install @slatis/sdk
// app/book/layout.tsx
import { SlatisProvider } from '@slatis/sdk/react'
 
export default function BookingLayout({ children }) {
  return (
    <SlatisProvider apiKey={process.env.NEXT_PUBLIC_SLATIS_KEY!}>
      {children}
    </SlatisProvider>
  )
}

2. Fetch available slots

'use client'
import { useAvailability } from '@slatis/sdk/react'
import { addDays } from 'date-fns'
 
export function SlotPicker({ eventTypeId, onSelect }) {
  const { slots, isLoading } = useAvailability({
    eventTypeId,
    startDate: new Date(),
    endDate: addDays(new Date(), 7),
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
  })
 
  if (isLoading) return <p>Loading slots...</p>
 
  return (
    <ul>
      {slots.map((slot) => (
        <li key={slot.start}>
          <button onClick={() => onSelect(slot)}>
            {new Date(slot.start).toLocaleTimeString()}
          </button>
        </li>
      ))}
    </ul>
  )
}

3. Collect attendee details

'use client'
import { useState } from 'react'
 
export function AttendeeForm({ onSubmit }) {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
 
  return (
    <form onSubmit={(e) => { e.preventDefault(); onSubmit({ name, email }) }}>
      <input value={name} onChange={(e) => setName(e.target.value)} placeholder="Name" required />
      <input value={email} onChange={(e) => setEmail(e.target.value)} type="email" placeholder="Email" required />
      <button type="submit">Continue</button>
    </form>
  )
}

4. Create the booking

'use client'
import { useSlatis } from '@slatis/sdk/react'
 
export function ConfirmStep({ eventTypeId, slot, attendee, onConfirmed }) {
  const slatis = useSlatis()
 
  async function confirm() {
    const booking = await slatis.bookings.create({
      eventTypeId,
      requestedTime: slot.start,
      attendee: {
        name: attendee.name,
        email: attendee.email,
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
      },
    })
    onConfirmed(booking)
  }
 
  return (
    <div>
      <p>Booking {new Date(slot.start).toLocaleString()} for {attendee.name}</p>
      <button onClick={confirm}>Confirm</button>
    </div>
  )
}

On this page