Calendar Outage Runbook
Symptom
/Resources/Calendar on launchindustries.biz loads, but no events appear. No error message to the user. The Navbar "Upcoming Classes" dropdown also shows nothing.
Architecture (so you know where to look)
Visitor browser
↓
React Query call to Supabase
↓
Supabase Edge Function: getAllCalendarEvents
↓
Google Calendar API (4 calendars)
↓
Google Cloud Service Account ← THIS is the single point of failureThe Supabase Edge Function getAllCalendarEvents reads four Google Calendars (Important Deadlines, Entrepreneurs Calendar, Launch & Learn Classes, Social Justice Calendar) using a Google Cloud service account. The service account's JSON key is stored on Supabase as the secret GOOGLE_SERVICE_ACCOUNT_JSON.
If the Google Cloud project that owns the service account is deleted, every calendar query starts returning HTTP 403 "Project has been deleted" — and the website calendar silently shows zero events. This already happened once (2026-05-26). Treat it as a real risk.
Diagnosis
Hit the edge function directly with debug mode
curl -X POST "https://egnrizeybeihfavzwxfe.supabase.co/functions/v1/getAllCalendarEvents" \
-H "Content-Type: application/json" \
-H "apikey: <SUPABASE_PUBLISHABLE_KEY>" \
-H "Authorization: Bearer <SUPABASE_PUBLISHABLE_KEY>" \
-d '{
"timeMin": "2026-05-20T00:00:00Z",
"timeMax": "2026-08-20T00:00:00Z",
"debug": true
}'The debug: true flag returns a per-calendar status array so you can see exactly which calendars are failing and why.
Read the debug array
If you see "Project #XXXXXXX has been deleted" for every calendar, the GCP project is gone. Skip to Recovery.
If you see "Insufficient Permission" for one specific calendar, the service account lost share access to that one calendar. Skip to Re-share a calendar.
If you see "events: []" but each calendar reports count: 0 with no error, there genuinely are no events in the date range. Not a system failure.
Check the Vercel logs (secondary)
If the edge function returns HTTP 5xx instead of 200 with empty events, check Supabase Edge Function logs:
# Supabase dashboard → Project → Edge Functions → getAllCalendarEvents → LogsRecovery: GCP project was deleted
Try to restore (only works within 30 days of deletion)
- Go to https://console.cloud.google.com/cloud-resource-manager (opens in a new tab)
- Look in the Pending deletion tab for the original project ID
- Click Restore
If the project is restored, the calendar will start working again in ~5 minutes with no other changes needed.
If restoration isn't possible, set up a new project
- Create a new project in Google Cloud Console (e.g.
launch-calendars). - Enable the Google Calendar API for the new project (APIs & Services → Enable APIs → Google Calendar API).
- Create a service account. IAM & Admin → Service Accounts → Create. Grant it no roles (it only needs calendar shares).
- Create a JSON key for the service account. Download the JSON file.
- Share each calendar with the new service account email. Open Google Calendar in your browser. For each of the four calendars (Important Deadlines, Entrepreneurs Calendar, Launch & Learn Classes, Social Justice Calendar): Settings → "Share with specific people" → add the new service account email (looks like
xxxxxx@launch-calendars.iam.gserviceaccount.com) with permission level "See all event details". - Update the Supabase secret. In the Supabase dashboard: Project Settings → Edge Functions → Secrets → replace
GOOGLE_SERVICE_ACCOUNT_JSONwith the contents of the new JSON file. No redeploy needed — the function reads the env var on every invocation. - Verify. Run the debug curl from the Diagnosis section above. You should see
events.length > 0and no errors.
Recovery: One calendar lost share access
This happens if someone in Google Calendar removed the service account from a calendar's sharing settings.
- Get the service account email from the Supabase secret
GOOGLE_SERVICE_ACCOUNT_JSON(theclient_emailfield). - Open the affected calendar in Google Calendar.
- Settings → "Share with specific people" → add the service account email back with "See all event details".
- Re-run the debug curl. The previously-failing calendar should now show a count.
Prevention
Before anyone "cleans up unused Google Cloud projects", make them check:
- Open the Supabase secret
GOOGLE_SERVICE_ACCOUNT_JSON. - Find the
project_idfield. - Do NOT delete that project, no matter how unused it looks.
Monitoring (recommended, not yet built): a daily Vercel Cron or Supabase Scheduled Function that hits getAllCalendarEvents and emails accounts@launchindustries.biz if events come back zero or with errors. ~15 minutes to wire up. This is the safety net for if the prevention rule above gets forgotten.
Reference: where to find things
| Thing | Where |
|---|---|
| Edge function source | Supabase dashboard → Edge Functions → getAllCalendarEvents |
| Service account JSON | Supabase dashboard → Edge Functions → Secrets → GOOGLE_SERVICE_ACCOUNT_JSON |
| Calendar IDs | Hard-coded in the edge function (4 of them) |
| GCP project | Whatever project_id is inside the service account JSON |
| Visitor-facing page | https://www.launchindustries.biz/Resources/Calendar (opens in a new tab) |
| Frontend component | src/components/calendar/UnifiedCalendar.jsx in the launchindustries-website repo |