diff --git a/backend/oauth_connect.json b/backend/oauth_connect.json
index bc2498a943..45ec3a655b 100644
--- a/backend/oauth_connect.json
+++ b/backend/oauth_connect.json
@@ -98,6 +98,39 @@
"prompt": "consent"
}
},
+ "gdocs": {
+ "auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
+ "token_url": "https://oauth2.googleapis.com/token",
+ "scopes": ["https://www.googleapis.com/auth/documents"],
+ "scope_options": [
+ "https://www.googleapis.com/auth/documents",
+ "https://www.googleapis.com/auth/documents.readonly",
+ "https://www.googleapis.com/auth/drive.file"
+ ],
+ "extra_params": {
+ "access_type": "offline",
+ "prompt": "consent"
+ }
+ },
+ "gchat": {
+ "auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
+ "token_url": "https://oauth2.googleapis.com/token",
+ "scopes": [
+ "https://www.googleapis.com/auth/chat.spaces.readonly",
+ "https://www.googleapis.com/auth/chat.messages.create"
+ ],
+ "scope_options": [
+ "https://www.googleapis.com/auth/chat.spaces.readonly",
+ "https://www.googleapis.com/auth/chat.messages",
+ "https://www.googleapis.com/auth/chat.messages.readonly",
+ "https://www.googleapis.com/auth/chat.messages.create",
+ "https://www.googleapis.com/auth/chat.memberships.readonly"
+ ],
+ "extra_params": {
+ "access_type": "offline",
+ "prompt": "consent"
+ }
+ },
"gcloud": {
"auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
"token_url": "https://oauth2.googleapis.com/token",
diff --git a/frontend/src/lib/components/AppConnectInner.svelte b/frontend/src/lib/components/AppConnectInner.svelte
index c695227964..6f5fa3c323 100644
--- a/frontend/src/lib/components/AppConnectInner.svelte
+++ b/frontend/src/lib/components/AppConnectInner.svelte
@@ -449,16 +449,15 @@
// Google's terms require its own button on the control that starts the sign-in, which is
// the step-2 Connect: step 1 only picks a type, and a manual step 2 saves a resource
- // without ever reaching Google.
+ // without ever reaching Google. Every registry provider that signs in through Google's
+ // authorize endpoint counts; `google` itself is a login provider, not a registry entry.
run(() => {
isGoogleSignin =
step == 2 &&
!manual &&
(resourceType == 'google' ||
- resourceType == 'gmail' ||
- resourceType == 'gcal' ||
- resourceType == 'gdrive' ||
- resourceType == 'gsheets')
+ (registryEntryFor(resourceType)?.auth_url?.startsWith('https://accounts.google.com/') ??
+ false))
})
run(() => {
diff --git a/frontend/src/lib/components/AuthSettings.svelte b/frontend/src/lib/components/AuthSettings.svelte
index c5f0a2040a..7bf7718e49 100644
--- a/frontend/src/lib/components/AuthSettings.svelte
+++ b/frontend/src/lib/components/AuthSettings.svelte
@@ -80,6 +80,8 @@
'gmail',
'gcal',
'gforms',
+ 'gdocs',
+ 'gchat',
'gcloud',
'gworkspace',
'basecamp',
diff --git a/frontend/src/lib/components/icons/BRAND_COLORS.md b/frontend/src/lib/components/icons/BRAND_COLORS.md
index 11d4df5c3b..c15537b6e1 100644
--- a/frontend/src/lib/components/icons/BRAND_COLORS.md
+++ b/frontend/src/lib/components/icons/BRAND_COLORS.md
@@ -137,6 +137,7 @@ repeatedly — check the brand's own page.
| `FunkwhaleIcon` | `funkwhale` | mixed | #009FE3 | #009FE3 | 10.69 | 5.71 | www.funkwhale.audio/logos (theme/images/icon.svg) |
| `GSheetsIcon` | `gsheets` | fixed | #009954 | #009954 | 3.57 | 12.47 | Google product logo sheets_2026q3 (gstatic productlogos, used on workspace.google.com/products/sheets) |
| `GcalIcon` | `gcal` | fixed | #BBE2FF | #BBE2FF | 3.40 | 12.47 | Google's own Calendar 2026 product logo, https://www.gstatic.com/images/branding/productlogos/calendar_2026/v2/web/192px.svg (paths verbatim) |
+| `GchatIcon` | `gchat` | fixed | #0EBC5F | #0EBC5F | 2.80 | 4.98 | Google's own Chat 2026 product icon, https://www.gstatic.com/images/branding/productlogos/chat_2026/v2/web/192px.svg (paths verbatim, ids namespaced) |
| `GdocsIcon` | `gdocs` | inherits | #718096 | #A9B0BA | 3.88 | 5.71 | Google's own Docs product icon (gstatic.com/images/branding/productlogos/docs_2026/v2/web/192px.svg, served on workspace.google.com/products/docs) |
| `GdriveIcon` | `gdrive` | fixed | #B43333 | #B43333 | 5.87 | 10.05 | https://www.gstatic.com/images/branding/productlogos/drive_2026/v2/web/192px.svg, Google's own product-logo CDN; paths and gradient stops are verbatim |
| `GhostCmsIcon` | `ghostcms` | pair | #15171A | #FFFFFF | 17.38 | 12.47 | docs.ghost.org |
diff --git a/frontend/src/lib/components/icons/GchatIcon.svelte b/frontend/src/lib/components/icons/GchatIcon.svelte
new file mode 100644
index 0000000000..3260f71971
--- /dev/null
+++ b/frontend/src/lib/components/icons/GchatIcon.svelte
@@ -0,0 +1,65 @@
+
+
+
+
diff --git a/frontend/src/lib/components/icons/index.ts b/frontend/src/lib/components/icons/index.ts
index 825f671e43..bbefc16469 100644
--- a/frontend/src/lib/components/icons/index.ts
+++ b/frontend/src/lib/components/icons/index.ts
@@ -33,6 +33,7 @@ import StripeIcon from './StripeIcon.svelte'
import TelegramIcon from './TelegramIcon.svelte'
import FunkwhaleIcon from './FunkwhaleIcon.svelte'
import GdocsIcon from './GdocsIcon.svelte'
+import GchatIcon from './GchatIcon.svelte'
import NextcloudIcon from './NextcloudIcon.svelte'
import NetsuiteIcon from './NetsuiteIcon.svelte'
import FaunadbIcon from './FaunadbIcon.svelte'
@@ -386,6 +387,7 @@ export const APP_TO_ICON_COMPONENT = {
helper: WindmillIcon,
windmillhub: WindmillIcon,
gdocs: GdocsIcon,
+ gchat: GchatIcon,
ocs: NextcloudIcon,
faunadb: FaunadbIcon,
clickhouse: ClickhouseIcon,
@@ -715,6 +717,7 @@ export {
DatadogIcon,
FunkwhaleIcon,
GdocsIcon,
+ GchatIcon,
FaunadbIcon,
ClickhouseIcon,
OpenaiIcon,