Works with Nuxt and SSR
Components render on the server. Google's script loads once the page reaches the browser, then isReady turns true.
Google's sign-in button, One Tap and OAuth2 token and code flows, as one Vue component and three composables.
pnpm add vue3-google-signinYour Vue app
<GoogleSignInButton @success="onSuccess"/>onSuccess({ credential })ID token
eyJhbGciOiJSUzI1NiIsImtpZCI6….eyJpc3MiOiJhY2NvdW50cy5nb29nbGU….c2lnbmF0dXJl…decodeCredential()Signed in
Google runs the account picker and consent screens. Your app gets a token and decides what to do with it.
GoogleSignInButton renders it, or useOneTap shows Google's prompt. Google's script loads once.
In Google's own window, so passwords never touch your app.
An ID token that says who signed in, or an access token or code for Google APIs.
Check the token's signature with Google's public keys, then start a session.
Follow the questions to the flow that fits, then compare its code and what your app gets back. Each one is a few lines of Vue.
What do you need from Google?
To know who the user is
To call Google APIs
When they click
On its own
In the browser
On your server
Google's own button. Users pick an account and you get an ID token that says who they are.
<script setup>import { ref } from "vue";import { GoogleSignInButton, decodeCredential,} from "vue3-google-signin";
const user = ref(null);const onSuccess = ({ credential }) => { user.value = decodeCredential(credential);};</script>
<template> <GoogleSignInButton @success="onSuccess" /> <p v-if="user">Signed in as {{ user.email }}</p></template>@success receives
This button is live. Sign in to see the token your app receives.
eyJhbGciOiJSUzI1NiIsImtpZCI6ImV4YW1wbGUiLCJ0….eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5j….ZXhhbXBsZS1zaWduYXR1cmUtbm90LWEtcmVhbC1vbmU Decoded in your browser with decodeCredential(). Nothing is sent to a server.
Decode it for the user's name, email and picture, and verify it on your server. Button guide
Google's prompt in the corner of the page. Returning users sign in with one tap, no button needed.
<script setup>import { useOneTap } from "vue3-google-signin";
useOneTap({ onSuccess: ({ credential }) => { // Send the credential to your server to sign the user in },});</script>onSuccess receives
{credential: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjVhYz…",select_by: "user",}The same ID token as the button. Add autoSelect to skip the tap for returning users. One Tap guide
Your own button opens Google's consent popup. You get an access token to call Google APIs from the browser.
<script setup>import { useTokenClient } from "vue3-google-signin";
const { isReady, login } = useTokenClient({ scope: "https://www.googleapis.com/auth/drive.readonly", onSuccess: ({ access_token }) => { // Call the Google Drive API with the token },});</script>
<template> <button :disabled="!isReady" @click="login()"> Connect Google Drive </button></template>onSuccess receives
{access_token: "ya29.a0AeDClZBx7Kq…",token_type: "Bearer",expires_in: 3599,scope: "email profile openid https://www.googleapis.com/auth/drive.readonly" ,}The token lasts about an hour, and users can untick scopes, so check what they granted. Custom buttons guide
Your own button again, but Google returns a one-time code. Your server exchanges it for access and refresh tokens.
<script setup>import { useCodeClient } from "vue3-google-signin";
const { isReady, login } = useCodeClient({ scope: "https://www.googleapis.com/auth/calendar.readonly", onSuccess: ({ code }) => { // Your server swaps the code for tokens fetch("/api/google", { method: "POST", body: code }); },});</script>
<template> <button :disabled="!isReady" @click="login()"> Sync my calendar </button></template>onSuccess receives
{code: "4/0AeaYSHDqvN8…" ,scope: "email profile openid https://www.googleapis.com/auth/calendar.readonly" ,}The refresh token stays on your server, so it can act for the user while they're away. Exchange the code
It handles the parts around Google’s script, so your own code stays small.
Components render on the server. Google's script loads once the page reaches the browser, then isReady turns true.
4.3 kB gzipped, about 4% of Google's own script. Vue is the only peer dependency.
Options and responses are typed, so your editor lists the fields.
Set the client ID from your server, switch it per tenant, or give each component its own. See how
onNonOAuthError tells you, so you can re-enable your button.
Projects like these sign users in with it, along with hundreds more on GitHub. Using it too? Add yours.
57.9K
in September 2026, both packages together
187
since July 2022
545
plus 299 through the Nuxt module
| Month | vue3-google-signin | Nuxt module | Total |
|---|---|---|---|
| October 2025 | 35,623 | 19,646 | 55,269 |
| November 2025 | 32,936 | 18,368 | 51,304 |
| December 2025 | 33,449 | 18,513 | 51,962 |
| January 2026 | 32,302 | 15,997 | 48,299 |
| February 2026 | 34,308 | 15,933 | 50,241 |
| March 2026 | 43,416 | 21,373 | 64,789 |
| April 2026 | 42,250 | 19,453 | 61,703 |
| May 2026 | 37,113 | 18,208 | 55,321 |
| June 2026 | 36,989 | 18,315 | 55,304 |
| July 2026 | 36,154 | 16,627 | 52,781 |
| August 2026 | 34,732 | 16,779 | 51,511 |
| September 2026 | 39,443 | 18,424 | 57,867 |
| Month | Stars |
|---|---|
| July 2022 | 29 |
| August 2022 | 39 |
| September 2022 | 43 |
| October 2022 | 45 |
| November 2022 | 50 |
| December 2022 | 51 |
| January 2023 | 61 |
| February 2023 | 65 |
| March 2023 | 73 |
| April 2023 | 78 |
| May 2023 | 79 |
| June 2023 | 82 |
| July 2023 | 86 |
| August 2023 | 88 |
| September 2023 | 93 |
| October 2023 | 100 |
| November 2023 | 103 |
| December 2023 | 107 |
| January 2024 | 113 |
| February 2024 | 117 |
| March 2024 | 125 |
| April 2024 | 127 |
| May 2024 | 131 |
| June 2024 | 132 |
| July 2024 | 139 |
| August 2024 | 144 |
| September 2024 | 149 |
| October 2024 | 154 |
| November 2024 | 158 |
| December 2024 | 161 |
| January 2025 | 165 |
| February 2025 | 167 |
| March 2025 | 168 |
| April 2025 | 173 |
| May 2025 | 173 |
| June 2025 | 175 |
| July 2025 | 176 |
| August 2025 | 176 |
| September 2025 | 179 |
| October 2025 | 181 |
| November 2025 | 184 |
| December 2025 | 185 |
| January 2026 | 185 |
| February 2026 | 185 |
| March 2026 | 185 |
| April 2026 | 186 |
| May 2026 | 186 |
| June 2026 | 187 |
| July 2026 | 187 |
| August 2026 | 187 |
| September 2026 | 187 |
| October 2026 | 187 |
pnpm add vue3-google-signinimport { createApp } from "vue";import GoogleSignInPlugin from "vue3-google-signin";import App from "./App.vue";
createApp(App) .use(GoogleSignInPlugin, { clientId: "YOUR_CLIENT_ID.apps.googleusercontent.com", }) .mount("#app");Drop in GoogleSignInButton or one of the composables from the flows above, then follow the guide for your setup.