How it works
Lead capture first
Name, email, phone, custom intake questions. Captured before the calendar shows, so the lead is logged even if the visitor drops off.
Availability read
Google Calendar FreeBusy API checks the real calendar. Busy times are subtracted from the configured weekly hours.
Rules layer
Admin settings apply: date overrides (holidays, vacation), minimum notice, buffer times before and after, event-type durations.
Slot selection
Visitor sees only valid slots. react-day-picker renders the UI, slots computed server-side. Server-side rate limiting blocks abuse.
Confirm + Meet link
On confirm, the calendar event is created and a fresh Google Meet link is auto-generated in the invite.
Logged to DB
A row is appended with timestamp, name, email, phone, slot, event type, status, and intake answers. The lead trail stays clean.
Why not Calendly
Two reasons. First, I wanted the lead-capture-first flow, which Calendly doesn't do. Second, I wanted to learn the Google Calendar end to end on something real. The site you're reading uses this booking engine for every call scheduled.
Stack
Next.js 15 App Router with TypeScript. NextAuth with Google OAuth for admin. Google Calendar (FreeBusy). react-day-picker for the calendar UI, shadcn/ui for everything else. Server-side rate limiting on the booking endpoint. JSON-file storage for the admin config; Back End is the source of truth for bookings.