Appointment Booking App Template: Build a Scheduling Platform
Appointment booking systems power healthcare, beauty, fitness, consulting, and service businesses. The market for scheduling software continues to grow as more service businesses move online. Building a booking platform requires calendar management, availability logic, payment processing, and notification systems.
An appointment booking app template provides all of this infrastructure pre-built.
Key Platform Features
A production-ready booking template includes:
- Service provider profiles
- Availability calendar with time slots
- Online booking with instant confirmation
- Payment collection at booking
- Automated reminders (email + SMS)
- Cancellation and rescheduling
- Staff management
- Customer history
The RentEasy template includes booking and scheduling functionality.
Availability Calendar
// lib/booking/availability.ts
import { prisma } from '@/lib/prisma'
interface TimeSlot {
start: Date
end: Date
available: boolean
}
export async function getAvailableSlots(
providerId: string,
date: Date,
serviceDuration: number
): Promise<TimeSlot[]> {
const dayOfWeek = date.getDay()
const availability = await prisma.availability.findFirst({
where: { providerId, dayOfWeek },
})
if (!availability) return []
const existingBookings = await prisma.booking.findMany({
where: {
providerId,
date: {
gte: new Date(date.setHours(0, 0, 0, 0)),
lt: new Date(date.setHours(23, 59, 59, 999)),
},
status: { not: 'cancelled' },
},
})
const slots: TimeSlot[] = []
const startHour = availability.startHour
const endHour = availability.endHour
for (let hour = startHour; hour < endHour; hour++) {
const slotStart = new Date(date)
slotStart.setHours(hour, 0, 0, 0)
const slotEnd = new Date(slotStart)
slotEnd.setMinutes(slotStart.getMinutes() + serviceDuration)
const conflict = existingBookings.some(booking => {
const bStart = new Date(booking.date)
const bEnd = new Date(bStart)
bEnd.setMinutes(bStart.getMinutes() + booking.duration)
return slotStart < bEnd && slotEnd > bStart
})
slots.push({
start: slotStart,
end: slotEnd,
available: !conflict,
})
}
return slots
}Booking Widget
'use client'
import { useState } from 'react'
import { Calendar } from 'lucide-react'
interface TimeSlot {
time: string
available: boolean
}
export function BookingWidget() {
const [selectedDate, setSelectedDate] = useState('')
const [selectedSlot, setSelectedSlot] = useState('')
const [slots, setSlots] = useState<TimeSlot[]>([])
const handleDateChange = async (date: string) => {
setSelectedDate(date)
setSelectedSlot('')
const res = await fetch(`/api/slots?date=${date}`)
const data = await res.json()
setSlots(data)
}
return (
<div className="rounded-xl border bg-white p-6">
<h3 className="text-lg font-semibold">Book an Appointment</h3>
<div className="mt-4">
<label className="text-sm font-medium">Select Date</label>
<div className="relative mt-1">
<Calendar className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400" />
<input
type="date"
value={selectedDate}
onChange={e => handleDateChange(e.target.value)}
className="w-full rounded-xl border py-2.5 pl-10 pr-4"
/>
</div>
</div>
{slots.length > 0 && (
<div className="mt-4">
<label className="text-sm font-medium">Available Times</label>
<div className="mt-2 grid grid-cols-3 gap-2">
{slots.map((slot, i) => (
<button
key={i}
onClick={() => setSelectedSlot(slot.time)}
disabled={!slot.available}
className={`rounded-lg border py-2 text-sm font-medium ${
selectedSlot === slot.time
? 'border-brand-600 bg-brand-50 text-brand-700'
: slot.available
? 'hover:border-brand-300'
: 'bg-gray-50 text-gray-300 cursor-not-allowed'
}`}
>
{slot.time}
</button>
))}
</div>
</div>
)}
<button
disabled={!selectedSlot}
className="mt-6 w-full rounded-xl bg-brand-600 py-3 font-semibold text-white disabled:opacity-50"
>
Confirm Booking
</button>
</div>
)
}Build your scheduling platform with the RentEasy booking template.
Browse all 200+ templates and starter kits.
Related Template
Try this production-ready starter kit to build your project faster.
Select Date & Time
Restaurant Booking
Reserve tables, manage guests, grow revenue
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits