> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vibestrap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Google One-Tap

> Frictionless one-click sign-in for users with an active Google session — already wired via Better Auth's One-Tap plugin.

Google One-Tap is the little popup card that appears top-right when a signed-out
visitor lands on your home page and they have an active Google session. One click
and they're signed in — no redirect, no form. Vibestrap wires it via Better Auth's
One-Tap plugin and a tiny client component (`src/components/auth/one-tap.tsx`).

It uses [FedCM](https://developers.google.com/privacy-sandbox/3pcd/fedcm), Google's
newer browser API that doesn't depend on third-party cookies — which means it'll
keep working as Chrome phases those out.

## Prerequisites

* [Google OAuth](/auth/google-oauth) already set up. One-Tap reuses the same
  OAuth client, so `GOOGLE_CLIENT_ID` must already exist.
* A `NEXT_PUBLIC_GOOGLE_CLIENT_ID` env var — the public mirror of the same ID.
* HTTPS in production. (HTTP works on `localhost` for dev.)

## Step-by-step setup

1. **Mirror the client ID into the public env.** Better Auth's One-Tap plugin
   needs the ID on the client too — add to `.env.local`:

   ```bash theme={null}
   NEXT_PUBLIC_GOOGLE_CLIENT_ID=1234567890-abc...apps.googleusercontent.com
   ```

   Same value as `GOOGLE_CLIENT_ID`. It's safe to expose; it's a public identifier.

2. **Turn the feature on.** In `src/config/site.ts`:

   ```ts theme={null}
   features: { enableOneTap: true, /* ... */ }
   ```

3. **Confirm the component is mounted.** It already lives in
   `src/app/layout.tsx` (or the locale layout) inside the `NextIntlClientProvider`
   so it's alive across every page. The component renders nothing — it just listens
   for an idle moment to call `authClient.oneTap()`.

4. **Restart `pnpm dev`.** Public env vars are baked at build/dev start.

## How it actually works

`src/components/auth/one-tap.tsx` is a 30-line `'use client'` component:

```tsx theme={null}
const { data: session, isPending } = useSession();
useEffect(() => {
  if (isPending || session) return;
  authClient.oneTap?.().catch(() => {});
}, [isPending, session]);
```

If the user is signed in, it does nothing. If not, it asks Better Auth's plugin to
prompt Google. Errors are swallowed because every reason a One-Tap can fail
(ineligible browser, dismissed, no Google session) is non-actionable for the user.

The "Continue with Google" button on `/login` and the One-Tap popup are independent —
both can be active at the same time. One-Tap just makes the home page lighter.

The matching client config is in `src/lib/auth-client.ts`:

```ts theme={null}
oneTapClient({
  clientId: googleClientId,
  autoSelect: false,         // user must click — never auto-pick
  cancelOnTapOutside: true,  // dismissable
  context: 'signin',
})
```

`autoSelect: false` is deliberate — auto-signing someone in without their click is
exactly the kind of dark pattern you want to avoid, and Google penalises it on
`accounts.google.com`. Leave it off.

## Verify it works

1. Make sure you have a Google account signed in (in another tab) and you are not
   signed in to your Vibestrap site.
2. Open the home page in an incognito window with that Google session present.
3. Within a second or two, the One-Tap card should slide in from the top-right.
4. Click it — you're signed in, no redirect.

If nothing appears, open DevTools → Network → filter for `accounts.google.com` to
see whether the FedCM request was sent.

## Common pitfalls

* **Works locally, dead in production.** Almost always missing
  `NEXT_PUBLIC_GOOGLE_CLIENT_ID` in your hosting provider's env config (Vercel,
  Netlify, etc.). Public env vars are baked at build time — set them, then redeploy.
* **HTTPS required.** Production hosts must serve over HTTPS. `localhost` is the
  one HTTP exception browsers allow.
* **Brave or Safari shows nothing.** FedCM is gated behind a setting in Brave
  (Shields) and is still rolling out in Safari. Don't treat the One-Tap as the only
  way in — keep the regular button.
* **User has multiple Google accounts.** Instead of an instant sign-in card, they
  see an account chooser. Same plugin, just a different UI from Google's side —
  nothing to fix on your end.
* **Card appears but click does nothing.** Usually means your OAuth client's
  authorized JavaScript origins don't include the current host. Add it in the
  Google Cloud Console under your OAuth 2.0 Client ID → Authorized JavaScript origins.

## Official docs

* One-Tap features overview — [developers.google.com/identity/gsi/web/guides/features](https://developers.google.com/identity/gsi/web/guides/features)
* FedCM migration guide — [developers.google.com/identity/gsi/web/guides/fedcm-migration](https://developers.google.com/identity/gsi/web/guides/fedcm-migration)
* Display the One-Tap prompt — [developers.google.com/identity/gsi/web/guides/display-one-tap](https://developers.google.com/identity/gsi/web/guides/display-one-tap)
* Better Auth One-Tap plugin — [better-auth.com/docs/plugins/one-tap](https://www.better-auth.com/docs/plugins/one-tap)
