Google Workspace Integration
Knowledge > Integrations > Google Workspace
What it is / why we use it
Google Workspace (john@churchwiseai.com) underlies several distinct integrations: Gmail and Calendar access in Claude Code sessions via MCP plugins, a Google Drive sync that mirrors the knowledge repo to Google Docs nightly, Google Calendar surfaced in the founder dashboard, and Google OAuth for ShareWiseAI's social media publishing. These are all separate OAuth flows with different scopes sharing the same Google Cloud project credentials.
Account Info
- Google account: john@churchwiseai.com (Google Workspace)
- Google Cloud project: Credentials stored as
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET - OAuth tokens for founder tools: Stored in
founder_google_tokensSupabase table (single row, access + refresh token) - MCP plugins in Claude sessions: Gmail MCP currently connected to pastorjohnmoelker@gmail.com (FA-007 pending: needs re-auth to john@churchwiseai.com); Calendar MCP uses
mcp__claude_ai_Google_Calendar__gcal_*tools
How Used Per Product
| Product / Context | Feature | Details |
|---|---|---|
| Founder dashboard (churchwiseai-web) | Google Calendar tab | Lists events from all connected calendars; same OAuth token as Drive |
| Founder dashboard (churchwiseai-web) | Google Drive tab | Browse My Drive, Shared Drives, search files |
| churchwiseai-web (cron) | knowledge → Drive sync | Nightly at 7:30 UTC, converts YAML/Markdown to Google Docs in named Drive folders |
| ShareWiseAI (churchwiseai-web) | Google OAuth for social posting | Churches connect Google (YouTube) as a publishing destination |
| Claude Code sessions | Gmail MCP | Read/search/draft emails as john@churchwiseai.com (blocked pending FA-007) |
| Claude Code sessions | Calendar MCP | View/create/update calendar events in sessions |
| All codebases | Google Places API | Church location data enrichment (GOOGLE_PLACES_API_KEY) |
Google Cloud Console — Authorized Redirect URIs
Dashboard: https://console.cloud.google.com/apis/credentials → OAuth 2.0 Client IDs → the client used for GOOGLE_CLIENT_ID
IMPORTANT: Google Cloud Console does NOT support wildcards for redirect URIs. Every URI must be listed explicitly. This is different from Supabase (which supports
/**). Addingchurchwiseai.com/**does nothing — each path must be individually registered.
Source of truth: This section IS the canonical list. If you change the Google Cloud Console, update this section in the same session. If the list and the console disagree, the console is authoritative but this doc must be corrected immediately.
Canonical Authorized Redirect URI List
# Production — Founder OAuth (Calendar + Drive)
https://churchwiseai.com/api/founder/google-auth/callback
# Production — ShareWiseAI Social OAuth (YouTube/Google)
https://churchwiseai.com/api/social/platforms/callback
# Local development — Founder OAuth
http://localhost:3002/api/founder/google-auth/callback
# Local development — ShareWiseAI Social OAuth
http://localhost:3002/api/social/platforms/callback
Total: 4 URIs
How Each URI Is Constructed (code reference)
| URI | Source |
|---|---|
churchwiseai.com/api/founder/google-auth/callback | GOOGLE_REDIRECT_URI env var (explicit override). Falls back to VERCEL_URL (preview deployments) or localhost:3002. |
churchwiseai.com/api/social/platforms/callback | NEXT_PUBLIC_SITE_URL env var + /api/social/platforms/callback. Hardcoded to churchwiseai.com in production. |
Vercel Preview Deployments
- Founder OAuth in previews: The code falls back to
https://{VERCEL_URL}/api/founder/google-auth/callback. This URI is NOT registered in Google Cloud Console — Google will reject it. Founder OAuth does not work on Vercel preview deployments unless the specific preview URL is manually added. This is acceptable (founder auth is not tested in previews). - Social OAuth in previews: Uses
NEXT_PUBLIC_SITE_URLwhich ishttps://churchwiseai.com— redirects to production callback. Social OAuth in preview deployments always routes through production.
Adding New Redirect URIs
When a new OAuth flow is added (new property, new callback path):
- Add the URI to Google Cloud Console → Credentials → OAuth 2.0 Client → Authorized redirect URIs
- Add to the canonical list above
- Update
last-verifieddate below
OAuth Flows — Two Distinct Flows
1. Founder OAuth (Calendar + Drive)
Used by the founder dashboard and the nightly sync cron.
- Initiate:
GET /api/founder/google-auth?token={FOUNDER_TOKEN} - Scopes requested:
calendar.readonly,calendar.events,drive.readonly,drive.file - Callback:
/api/founder/google-auth/callbackexchanges code for tokens, stores infounder_google_tokens - Token refresh:
google-calendar.ts:refreshAccessToken()— automatic refresh 5 minutes before expiry, stores newaccess_tokenin Supabase - Login hint:
john@churchwiseai.comis passed aslogin_hintto prevent wrong-account selection - Prompt:
consent(forces consent screen to obtainrefresh_tokenevery time)
2. ShareWiseAI Social OAuth
Used by church admins to connect Google/YouTube for social posting.
- Initiate:
GET /api/social/platforms/connect— generates authorization URL with PKCE nonce - Nonce storage:
social_oauth_noncestable in Supabase (prevents CSRF) - Callback:
/api/social/platforms/callback— exchanges code, stores encrypted tokens for the church's social account - Token refresh:
/api/social/cron/token-refresh— cron job refreshes expiring social platform tokens - Shares
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRETwith the founder OAuth flow (same Google Cloud project)
Knowledge → Drive Sync (Nightly Cron)
Route: churchwiseai-web/src/app/api/founder/sync-knowledge/route.ts
Schedule: 7:30 UTC daily (see vercel.json)
Auth: Vercel Cron header (Authorization: Bearer {CRON_SECRET}) or ?token={FOUNDER_TOKEN}
Max duration: 300 seconds (Vercel serverless limit override)
Source: Fetches files from the ChurchWiseAI/knowledge GitHub repo via GITHUB_TOKEN (fine-grained PAT, read access)
Sync map (source → Drive folder → title):
| Source | Drive Folder | Doc Title |
|---|---|---|
data/pricing.yaml | Pricing | ChurchWiseAI Pricing Guide |
data/features.yaml | Products | Product Feature Matrix |
data/products.yaml | Products | Product Portfolio Overview |
data/policies.yaml | Legal | Policies & Terms Summary |
narrative/vision.md | Company | Company Vision & Mission |
narrative/strategy.md | Roadmap | Go-to-Market Strategy |
narrative/brand.md | Brand | Brand Guidelines |
narrative/competitive.md | Competitive | Competitive Positioning |
narrative/sales-playbook.md | Sales | Sales Demo Playbook |
narrative/customer-journey.md | Sales | Customer Journey Map |
narrative/operations.md | SOPs | Operations Guide |
Behavior: Upsert — finds existing Google Doc by name within the target folder, updates it if found, creates if not. Folders must be created manually in Drive first (the sync does not create folders). If a folder is missing, that entry fails with an error in the response.
Duplicate converter note: The markdown-to-HTML converter in the route is a standalone copy of knowledge/scripts/derive-gdrive.ts. If you update conversion logic, update both files.
Key Environment Variables
| Variable | Used In | Purpose |
|---|---|---|
GOOGLE_CLIENT_ID | churchwiseai-web | OAuth client ID (shared by founder tools and ShareWiseAI) |
GOOGLE_CLIENT_SECRET | churchwiseai-web | OAuth client secret |
GOOGLE_REDIRECT_URI | churchwiseai-web | Override for founder OAuth callback URI (defaults to Vercel URL) |
GOOGLE_PLACES_API_KEY | churchwiseai-web | Google Places API for church location data |
GITHUB_TOKEN | churchwiseai-web | Fine-grained PAT (read-only) for fetching ChurchWiseAI/knowledge repo files |
CRON_SECRET | churchwiseai-web | Authenticates the Vercel cron invocation of the sync route |
FOUNDER_TOKEN | churchwiseai-web | Manual trigger auth for sync and OAuth initiation |
CLI / API Patterns & Gotchas
No googleapis npm package:
Both google-calendar.ts and google-drive.ts use raw fetch() against the REST API. No googleapis or google-auth-library npm packages. This keeps the bundle lean and avoids Node.js-specific imports that fail in edge runtimes.
Token storage in Supabase:
Tokens are stored in founder_google_tokens (single row). There is no multi-user OAuth for the founder tools — it's always john@churchwiseai.com.
401 detection for Drive:
google-drive.ts has a throwIf401 helper that checks for expired tokens and throws a clear, actionable error message directing the founder to reconnect from the Calendar settings tab. This surfaces in the cron response JSON when tokens are stale.
MCP plugins vs. HTTP API:
- The Claude Code session MCP plugins (
mcp__claude_ai_Google_Calendar__*) are separate from the HTTP API used by the founder dashboard. They use different OAuth credentials managed by Anthropic's MCP infrastructure. - The founder dashboard uses the Google Calendar REST API directly via
google-calendar.tswith tokens stored in Supabase. - Do not confuse the two. The MCP tools are for agent-to-founder communication in sessions; the dashboard is for the founder's operational use.
GWS CLI: The GWS CLI is available in Claude Code sessions for managing Google Workspace administrative tasks as john@churchwiseai.com. Use for: user management, domain settings, group management. Not used in any codebase.
ShareWiseAI social OAuth encrypted tokens:
Social platform tokens (including Google/YouTube) are encrypted before storage using social-crypto.ts. The encryption key is SOCIAL_TOKEN_ENCRYPTION_KEY. Never store these as plaintext.
Failure Modes & Recovery
| Failure | Behavior | Recovery |
|---|---|---|
founder_google_tokens has no row | Sync returns 500 with "Google Drive not connected" | Re-run OAuth flow: visit /api/founder/google-auth?token={FOUNDER_TOKEN} |
| Access token expired (401) | throwIf401 throws clear error in sync | Token refreshes automatically if refresh token valid; else re-run OAuth |
| Refresh token revoked | Can't auto-refresh; 401 on all Drive calls | Re-run OAuth consent flow (always requests prompt: consent to get new refresh token) |
| Drive folder missing | That sync entry fails; others succeed | Create the missing folder in Drive manually, then re-trigger sync |
GITHUB_TOKEN not set or expired | Sync returns 500 immediately | Update PAT in Vercel env vars; fine-grained PAT needs contents: read on ChurchWiseAI/knowledge |
| MCP Gmail connected to wrong account | Gmail MCP reads personal inbox, not business inbox | Re-authorize MCP to john@churchwiseai.com (FA-007) |
| ShareWiseAI social token expired | Publishing fails silently | Token refresh cron runs nightly; manual retry via refresh endpoint |
Cost Model / Usage Limits
- Google Calendar/Drive API: Free within Google Workspace quota. Calendar: 1,000,000 requests/day. Drive: 1,000,000,000 bytes/day upload. Both are well within range for a solo founder dashboard.
- Google Places API: Billed per request ($5/1,000 for standard lookup). Used for church location enrichment. Monitor usage in Google Cloud Console.
- Google Cloud OAuth: Free. No per-request cost.
- Workspace plan: John@churchwiseai.com is on Google Workspace (Business Starter or higher). Standard costs apply.
See Also
- Cal.com Integration — Cal.com bookings appear in Google Calendar; founder calendar shows Cal.com entries
- Vercel Integration — Vercel Cron triggers the knowledge sync route
churchwiseai-web/src/lib/google-calendar.ts— Calendar API wrapperchurchwiseai-web/src/lib/google-drive.ts— Drive API wrapperchurchwiseai-web/src/app/api/founder/sync-knowledge/route.ts— Nightly cron