Prompt
How do I build team scheduling with shared calendars and availability?
Latest observation
Building team scheduling with shared calendars and availability usually comes down to 5 parts:
- User profiles and working preferences
- Calendar/event ingestion
- Availability calculation
- Scheduling rules and conflict resolution
- A UI for proposing and confirming times
Here’s a practical way to design it.
1) Model the core data
You’ll want a few main entities:
Users
idnametimezoneworking_hoursor weekly availabilityteam_id/ memberships- optional: vacation/OOO rules
Calendars
A user can have multiple calendars:
- personal
- work
- shared team calendars
- resource calendars (conference rooms, equipment)
Fields:
idowner_idorteam_idtype(personal,shared,resource)visibilitysource(internal, Google, Microsoft, etc.)
Events
Events block time or represent tentative holds.
idcalendar_idstart_atend_atstatus(busy,free,tentative,out_of_office)visibilitytitlerecurrence_ruleif recurring
Availability rules
A person may have:
- regular working hours
- exceptions for holidays, PTO, on-call, etc.
Example:
- Mon–Fri, 9am–5pm in America/New_York
- not available during lunch
- unavailable on holidays
2) Normalize everything to UTC, store timezones separately
This is important.
- Store event times in UTC
- Store the user’s and calendar’s timezone
- Convert for display only
This avoids DST bugs and cross-timezone conflicts.
3) Ingest calendar data
If you integrate with Google Calendar / Microsoft 365:
- sync events via API
- subscribe to webhook notifications when calendars change
- periodically reconcile in case webhooks fail
If building internally:
- write event CRUD
- allow shared calendars and subscriptions
For external sync:
- map external event IDs to internal IDs
- handle create/update/delete
- store sync cursor or sync token per calendar
4) Compute “free/busy” availability
Scheduling usually doesn’t need full event details, just whether a time slot is free.
Basic algorithm
For a requested meeting time range:
- Get all relevant calendars for attendees
- Fetch events in the time window
- Mark all
busyorout_of_officeintervals as blocked - Intersect blocked intervals across participants
- Return available windows
Example
If Alice is free 10–11 and Bob is free 10:30–12:
- common availability = 10:30–11
Suggested availability types
freebusytentativeout_of_officeworking_hours_only
You can treat tentative as:
- busy for “strict scheduling”
- soft-blocked for “best effort scheduling”
5) Handle recurring events and exceptions
Recurring events are where many schedulers get tricky.
Support:
- RRULE-like recurrence
- exceptions / overrides
- single-instance edits
When querying availability:
- expand recurrences only for the requested date range
- do not fully materialize infinite recurring series unless needed
Use libraries or standard recurrence formats if possible.
6) Define scheduling rules
A scheduler needs more than “everyone free.”
Common rules:
- meeting duration
- earliest/latest start
- participant priority
- required vs optional attendees
- working hours only
- room/resource constraints
- time-zone fairness
- round-robin for recurring meetings
- minimum notice before booking
Example rule set:
- 30-minute meeting
- between 9am and 5pm local time for all required attendees
- choose earliest common slot
- prefer slots where most optional attendees can join
- avoid lunch blocks
7) Build a slot-finding algorithm
A typical approach:
Step A: generate candidate slots
- based on working hours
- granularity like 5/10/15 minutes
Step B: eliminate blocked slots
- any overlap with busy events
- any overlap with OOO
- any outside working hours
Step C: rank remaining slots
Ranking factors:
- earliest
- fewer attendees impacted
- fairness across time zones
- fewer calendar transitions
- avoid fragmented schedules
For efficiency, merge busy intervals first, then scan for gaps.
8) Shared calendars: access control matters
You need permissions:
- owner
- admin
- editor
- viewer
- free/busy only
For team calendars:
- some events may be private but still block time
- viewers may see only availability, not titles/details
A common model:
- full details for authorized users
- free/busy only for others
9) UI/UX suggestions
A good scheduling UI usually includes:
- calendar grid
- attendee list with availability indicators
- timezone display
- suggested time slots
- drag-to-select with conflict warnings
- meeting room suggestions
- “find a time” button
Useful extras:
- show working hours per attendee
- highlight overlaps
- show “best times” with confidence
- allow tentative holds before final booking
10) API design example
You might expose endpoints like:
GET /availability?users=1,2,3&start=...&end=...&duration=30GET /calendarsGET /calendars/{id}/eventsPOST /eventsPATCH /events/{id}DELETE /events/{id}POST /schedule/find-times
Example availability response:
{
"requested_duration_minutes": 30,
"suggested_slots": [
{
"start": "2026-10-05T14:00:00Z",
"end": "2026-10-05T14:30:00Z",
"score": 0.92
}
]
}
11) Technical pitfalls to avoid
- DST issues: always use timezone-aware datetime handling
- Recurring event explosion: expand only in the queried range
- Race conditions: two people may book the same slot simultaneously
- Sync drift: external calendars can change without notice
- Privacy leaks: don’t expose event titles if only free/busy is allowed
- Performance: indexing by calendar + time range is critical
12) Suggested implementation architecture
A solid architecture looks like:
- Frontend: calendar UI + scheduling assistant
- API backend: event and availability logic
- DB: store calendars/events/permissions
- Sync workers: ingest external calendar updates
- Availability engine: computes free/busy and suggestions
- Notification service: invites, changes, reminders
13) Simple scheduling flow
- User creates meeting request
- System identifies required attendees and constraints
- Pull free/busy data
- Generate possible slots
- Present top suggestions
- User selects one
- System creates tentative events/holds
- On confirmation, finalize booking and send invites
14) If you want an MVP
Start small:
- one timezone at a time
- no recurrence at first
- internal calendars only
- simple free/busy availability
- one team calendar
- one meeting type
Then add:
- Google/Microsoft sync
- recurring events
- room booking
- smart ranking
- mobile notifications
If you want, I can also give you:
- a database schema
- a free/busy algorithm in pseudocode
- a sample API design
- a React calendar UI approach
- a Google Calendar/Microsoft integration plan