Database models
- User — central user entity with handle-based public booking pages
- ConnectedCalendar — OAuth integration for Google Calendar with token management
- ExternalEventMapping — maps internal booking IDs to external calendar event IDs
- CalendarBusyBlock — cached busy time blocks from external calendars
- EventType — configurable booking types with duration, buffer times, and AI settings
- Booking — actual meetings with host/invitee details, status tracking, and AI agenda generation
- AvailabilityRule — configurable working hours, buffer times, booking limits
- RescheduleRequest — tracks rescheduling requests with AI-suggested alternatives
Authentication & Google Calendar OAuth
- NextAuth.js integration with Google OAuth provider, automatic user handle generation from email, JWT-based session management with 30-day expiration
- OAuth2 client management with automatic token refresh (5-minute buffer before expiry), calendar connection API, primary calendar selection, and a sync API for fetching and caching busy time blocks
POST /api/auth/google-calendar/connect
GET /api/auth/google-calendar/connect
PATCH /api/auth/google-calendar/connect/primary
POST /api/auth/google-calendar/sync
DELETE /api/auth/google-calendar/sync
Core utilities live in /src/lib/calendar/google-calendar.ts (createOAuth2Client, refreshAccessToken, getValidOAuth2Client, createCalendarEvent, updateCalendarEvent, deleteCalendarEvent, getFreeBusy, listCalendarEvents, getPrimaryCalendarId) and /src/lib/utils/timezone.ts (timezone detection, validation, and conversion between IANA identifiers and UTC).
Availability calculation engine
The core scheduling logic lives in /src/lib/availability/calculate-availability.ts:
calculateAvailability()— main function that computes available slotscreateTimeIntervals()— creates time intervals based on availability rulesisWithinAvailabilityRule()— checks if time falls within defined rulescheckIntervalAvailability()— validates intervals against bookings and busy blocksformatAvailableSlotsForDisplay()/getAvailableSlotsByDay()— formats and groups slots for the frontend
Booking management sits in /src/lib/booking/create-booking.ts (createBooking, cancelBooking, getBookingByUid, getUpcomingBookings, getBookingCountForDate) and /src/lib/booking/booking-utils.ts (slot generation, date formatting, gap-finding between busy blocks, and slot validation against event-type constraints).
POST /api/availability - Calculate availability for booking
GET /api/availability - Get availability with default parameters
POST /api/bookings - Create a new booking
GET /api/bookings - Get bookings (by UID or upcoming for user)
DELETE /api/bookings - Cancel a booking
Key algorithms:
- Availability calculation merges database availability rules with external calendar busy blocks, handles buffer times before and after existing bookings, validates against daily/weekly booking limits, and respects minimum/maximum lead time constraints.
- Time slot generation creates 30-minute intervals, applies availability rule filters (days of week, time ranges, exclusions), and generates gaps between busy blocks.
- Booking validation checks slot availability, event type constraints, and overlap with existing bookings and calendar events.
AI natural language parser (Gemini)
/src/lib/ai/ai-client.ts is an OpenAI-compatible interface wrapping Gemini models (chatCompletion, streamChatCompletion, healthCheck), and /src/lib/ai/nlp-parser.ts handles the actual parsing: parseBookingRequest, suggestAlternativeTimes, generateMeetingAgenda, detectTimezoneFromMessage, validateTimeSuggestion.
POST /api/ai/parse-booking - Parse natural language booking request
POST /api/ai/reschedule-suggestions - Generate AI-powered reschedule alternatives
PATCH /api/ai/reschedule-suggestions - Accept/decline reschedule request
POST /api/ai/generate-agenda - Generate meeting agenda from notes
GET /api/ai/generate-agenda - Get existing agenda
Natural language booking: intent recognition (book, inquire, reschedule, cancel), relative and absolute date/time extraction (“next Tuesday”, “tomorrow 2pm”), duration parsing, time-of-day preferences, and confidence scoring on parsed information.
AI-powered rescheduling: evaluates both parties’ calendars, suggests 3 optimal alternatives, validates suggestions against user constraints, and stays aware of existing bookings and busy blocks.
Automated meeting prep: generates a 3-7 bullet agenda from booking notes, using the event title and attendee count for context, and skips regeneration if an agenda already exists.
The AI client is provider-agnostic by design:
// Easy provider switching
const ai = getAIClient('gemini-1.5-flash');
// Can switch to OpenAI, Claude, or other OpenAI-compatible providers
const ai = getAIClient('gpt-4'); // Just change model name!
Supported models: gemini-1.5-flash (fast, cost-effective) and gemini-1.5-pro (best quality for complex reasoning), with other OpenAI-compatible models swappable without code changes.
Environment setup
npm install
cp .env.example .env
# Edit .env with your credentials
npm run db:generate # Generate Prisma client
npm run db:push # Push database schema (dev)
npm run dev # Run development server
Required environment variables:
DATABASE_URL="postgresql://..."
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
GOOGLE_CALENDAR_CLIENT_ID="your-google-calendar-client-id"
GOOGLE_CALENDAR_CLIENT_SECRET="your-google-calendar-client-secret"
RESEND_API_KEY="your-resend-api-key"
OPENAI_API_KEY="your-openai-api-key"
Google Calendar OAuth setup: create a project in Google Cloud Console, enable the Google Calendar API, create OAuth 2.0 credentials (web application, redirect URI http://localhost:3000/api/auth/callback/google), and copy the client ID/secret into .env.
Tech stack
- Frontend: Next.js 16 with App Router, React 19, TypeScript
- Styling: Tailwind CSS
- Database: PostgreSQL with Prisma ORM
- Authentication: NextAuth.js with Google OAuth
- Calendar integration: Google Calendar API with
googleapis - Utilities: jose (JWT), nanoid (ID generation)
Development
npm run dev # Development
npm run build # Build
npm start # Start production
npm run db:generate # Generate Prisma client
npm run db:push # Push schema to database (dev)
npm run db:migrate # Run migrations
npm run db:studio # Open Prisma Studio
License
ISC