Problem
Members must manually add their ManageHub bookings to their personal calendars. There is no calendar sync integration, so booking reminders are missed and scheduling conflicts with external meetings are common. All major coworking platforms offer Google Calendar sync as a standard feature.
Proposed Solution
Create a new NestJS module at backend/src/calendar-sync/ using the googleapis npm package (npm install googleapis).
Entity: CalendarToken
id (UUID), userId (UUID FK → users, unique)
provider (enum: google — extensible for future providers)
accessToken (text, encrypted), refreshToken (text, encrypted)
expiresAt (timestamp)
calendarId (string — the user's selected Google Calendar ID)
createdAt, updatedAt
Endpoints:
| Method |
Path |
Access |
GET |
/calendar-sync/auth/google |
Authenticated — returns Google OAuth URL |
GET |
/calendar-sync/auth/google/callback |
OAuth callback (redirects back to frontend) |
DELETE |
/calendar-sync/disconnect |
Authenticated — revokes and deletes token |
GET |
/calendar-sync/status |
Authenticated — returns { connected: boolean, provider } |
Sync logic: Hook into confirm-booking.provider.ts and cancel-booking.provider.ts. When a booking is confirmed for a user with an active CalendarToken, create a Google Calendar event. When a booking is cancelled, delete the corresponding calendar event. Store the Google event ID on the booking entity (googleCalendarEventId nullable field).
Acceptance Criteria
Problem
Members must manually add their ManageHub bookings to their personal calendars. There is no calendar sync integration, so booking reminders are missed and scheduling conflicts with external meetings are common. All major coworking platforms offer Google Calendar sync as a standard feature.
Proposed Solution
Create a new NestJS module at
backend/src/calendar-sync/using thegoogleapisnpm package (npm install googleapis).Entity:
CalendarTokenid(UUID),userId(UUID FK → users, unique)provider(enum:google— extensible for future providers)accessToken(text, encrypted),refreshToken(text, encrypted)expiresAt(timestamp)calendarId(string — the user's selected Google Calendar ID)createdAt,updatedAtEndpoints:
GET/calendar-sync/auth/googleGET/calendar-sync/auth/google/callbackDELETE/calendar-sync/disconnectGET/calendar-sync/status{ connected: boolean, provider }Sync logic: Hook into
confirm-booking.provider.tsandcancel-booking.provider.ts. When a booking is confirmed for a user with an activeCalendarToken, create a Google Calendar event. When a booking is cancelled, delete the corresponding calendar event. Store the Google event ID on the booking entity (googleCalendarEventIdnullable field).Acceptance Criteria
googleapisinstalled and listed inpackage.jsonCalendarTokenGET /calendar-sync/auth/google/callbackexchanges the auth code for tokens and redirects to frontendCalendarSyncModuleis registered inAppModuleGOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REDIRECT_URI) are documented in.env.example