To use Google Meet with V0, create Next.js API routes that call the Google Calendar API to programmatically create Google Meet meeting links. Google Meet does not have its own standalone API — meetings are created by adding a conferenceData request to a Google Calendar event via the Calendar API. Store OAuth2 credentials in Vercel environment variables and build scheduling UIs in V0 that call your API routes.
Creating Google Meet Links and Scheduling Meetings from Your V0 App
Google Meet does not have its own standalone developer API for creating meetings. Instead, Meet links are generated through the Google Calendar API: when you create or update a Google Calendar event and include a conferenceData request with requestId, Google automatically provisions a Meet link and attaches it to the event. This architecture means integrating Meet into your V0 app is really a Google Calendar API integration that produces Meet links as a byproduct.
The most common use case for V0 apps is automated meeting scheduling: a user fills out a booking form, your app creates a Calendar event with the attendee's email, and the response includes a unique Google Meet link that both parties can join. This pattern is used by scheduling tools, customer success platforms, consultation booking systems, and HR interview schedulers.
Authentication is the most complex part of this integration. If your app creates meetings on behalf of a Google Workspace service account (for example, a company's meeting room calendar), you use a service account with domain-wide delegation. If your app creates meetings in individual users' Google Calendars (each user connecting their own Google account), you use the standard OAuth2 Authorization Code flow. For most V0 apps serving external users, the OAuth2 flow is appropriate; for internal Workspace automations, service account delegation is simpler.
Integration method
V0 generates the meeting scheduling UI while Next.js API routes use the Google Calendar API (googleapis npm package) with OAuth2 to create calendar events with Google Meet conference links attached. There is no standalone Google Meet API — meetings are created by passing conferenceDataVersion=1 and a ConferenceData request when creating or updating a Google Calendar event. The Google Meet link is returned in the event's conferenceData.entryPoints array.
Prerequisites
- A V0 account with a Next.js project at v0.dev
- A Google Cloud project with the Google Calendar API enabled at console.cloud.google.com
- OAuth2 Client ID and Client Secret (for user-facing apps) or a service account with domain-wide delegation (for Workspace automation)
- googleapis npm package installed in your Next.js project
- For OAuth2 flow: callback URI https://your-app.vercel.app/api/google/callback configured in Google Cloud Console → APIs & Services → Credentials
Step-by-step guide
Enable Google Calendar API and Create OAuth2 Credentials
Enable Google Calendar API and Create OAuth2 Credentials
Google Meet links are created through the Google Calendar API, so your first step is enabling that API and creating OAuth2 credentials in Google Cloud Console. Go to Google Cloud Console (console.cloud.google.com). Select or create a project. Go to APIs & Services → Library, search for 'Google Calendar API', and click Enable. Next, create OAuth2 credentials. Go to APIs & Services → Credentials → Create Credentials → OAuth client ID. Choose Web application as the application type. Add your redirect URIs: https://your-app.vercel.app/api/google/callback for production and http://localhost:3000/api/google/callback for local development. After creating the credentials, download the JSON file or copy the Client ID and Client Secret. You also need to configure the OAuth consent screen (APIs & Services → OAuth consent screen). For testing, choose External but add your own email as a test user — this lets you test the OAuth flow without going through Google's app verification process. For production apps used by external Google accounts, you will need to go through Google's verification process if your app requests sensitive scopes. The scope you need is https://www.googleapis.com/auth/calendar.events — this allows creating and reading calendar events. If you also need to read existing calendar data (for availability checking), add https://www.googleapis.com/auth/calendar.readonly. One important Google Meet-specific limitation: meeting recording links, attendance reports, and in-meeting chat transcripts are not accessible via API. The Calendar API only gives you the meeting link (join URL) and basic meeting metadata.
Pro tip: During development, add your own Google account as a test user in the OAuth consent screen. This lets you test the full OAuth flow without publishing the app or going through Google's verification process.
Expected result: Google Calendar API is enabled in your Google Cloud project. You have an OAuth2 Client ID and Client Secret with the correct redirect URIs configured. Your consent screen is set up with the calendar.events scope.
Implement Google OAuth2 Authentication
Implement Google OAuth2 Authentication
Google Calendar operations on behalf of users require OAuth2 authorization. Implement the authorization flow with two API routes: one to initiate authorization and one to handle the callback. Install the googleapis package: npm install googleapis. This is Google's official Node.js client library for all Google APIs. Create app/api/google/auth/route.ts. This route builds the Google authorization URL using the google.auth.OAuth2 client and redirects users to it. Set the scopes to include https://www.googleapis.com/auth/calendar.events and pass access_type=offline to receive a refresh token (so users do not need to re-authorize after their access token expires in one hour). Create app/api/google/callback/route.ts. This route receives the authorization code from Google, exchanges it for tokens using oauth2Client.getToken(code), stores the tokens, and redirects the user back to your app. The refresh_token in the response is particularly important — store it persistently (in a database or secure cookie) because Google only sends it on the first authorization unless the user explicitly re-grants access. For a simpler single-account setup (e.g., scheduling meetings in your own calendar on behalf of users), use a service account instead of OAuth2. This avoids the user-facing auth flow entirely but requires a Google Workspace account with domain-wide delegation enabled.
Create two Next.js API routes for Google OAuth2. app/api/google/auth/route.ts: build authorization URL using googleapis OAuth2 client with GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URI, scope 'https://www.googleapis.com/auth/calendar.events', access_type 'offline', prompt 'consent'. Redirect the user to it. app/api/google/callback/route.ts: receive the code param, exchange it for tokens using oauth2Client.getToken(code), store tokens in a secure httpOnly cookie, redirect to /dashboard.
Paste this in V0 chat
1// app/api/google/auth/route.ts2import { google } from 'googleapis';3import { NextResponse } from 'next/server';45export async function GET() {6 const oauth2Client = new google.auth.OAuth2(7 process.env.GOOGLE_CLIENT_ID,8 process.env.GOOGLE_CLIENT_SECRET,9 process.env.GOOGLE_REDIRECT_URI10 );1112 const authUrl = oauth2Client.generateAuthUrl({13 access_type: 'offline',14 prompt: 'consent',15 scope: [16 'https://www.googleapis.com/auth/calendar.events',17 ],18 });1920 return NextResponse.redirect(authUrl);21}2223// app/api/google/callback/route.ts24import { google } from 'googleapis';25import { NextRequest, NextResponse } from 'next/server';26import { cookies } from 'next/headers';2728export async function GET(request: NextRequest) {29 const { searchParams } = new URL(request.url);30 const code = searchParams.get('code');3132 if (!code) {33 return NextResponse.json({ error: 'No code provided' }, { status: 400 });34 }3536 const oauth2Client = new google.auth.OAuth2(37 process.env.GOOGLE_CLIENT_ID,38 process.env.GOOGLE_CLIENT_SECRET,39 process.env.GOOGLE_REDIRECT_URI40 );4142 const { tokens } = await oauth2Client.getToken(code);4344 const cookieStore = await cookies();45 cookieStore.set('google_tokens', JSON.stringify(tokens), {46 httpOnly: true,47 secure: process.env.NODE_ENV === 'production',48 maxAge: 30 * 24 * 60 * 60,49 path: '/',50 });5152 return NextResponse.redirect(new URL('/dashboard', request.url));53}Pro tip: Add prompt: 'consent' to your OAuth2 authorization URL to always request a refresh token. Without this, Google only sends a refresh token on the first authorization, meaning users who previously authorized your app will not get a refresh token on subsequent logins.
Expected result: Visiting /api/google/auth redirects to Google's OAuth consent screen. After authorizing, Google redirects to your callback URL and stores the tokens. The dashboard shows the user as connected.
Create the Google Meet Link Generation API Route
Create the Google Meet Link Generation API Route
With OAuth2 working, create the API route that generates Google Meet links. The route creates a Google Calendar event with conferenceDataVersion=1 and a conferenceData object containing a createRequest — this tells Google to provision a Meet conference and attach it to the event. Create app/api/meetings/create/route.ts. The route receives the meeting details in the request body (title, start time, end time, attendee emails), initializes the Google OAuth2 client with stored tokens, creates the calendar event with conferenceData, and returns the Meet link from the response. The conferenceData.entryPoints array in the response contains the join URLs. The entry point with entryPointType === 'video' is the main browser/app join URL. There may also be phone entry points for dial-in access. Adding attendees to the calendar event (attendees array with email fields) sends them Google Calendar invitations with the Meet link. Set sendNotifications: true on the event insert if you want Google to send invitation emails. Handle token expiration in the API route: if the googleapis client throws an error about an invalid grant or expired token, refresh the access token using the stored refresh token and retry the request. The googleapis library can handle this automatically if you call oauth2Client.setCredentials(tokens) with a valid refresh token — it will auto-refresh when needed.
Create a Next.js API route at app/api/meetings/create/route.ts. POST body: title, description, startTime (ISO string), endTime (ISO string), attendeeEmails (array). Retrieve google_tokens from cookies, set credentials on OAuth2 client. Use googleapis calendar.events.insert with calendarId 'primary', conferenceDataVersion 1, conferenceData { createRequest: { requestId: UUID } }, attendees array, start { dateTime: startTime }, end { dateTime: endTime }. Return meetLink from response.data.conferenceData.entryPoints[0].uri and eventId.
Paste this in V0 chat
1// app/api/meetings/create/route.ts2import { google } from 'googleapis';3import { NextRequest, NextResponse } from 'next/server';4import { cookies } from 'next/headers';5import { randomUUID } from 'crypto';67export async function POST(request: NextRequest) {8 const body = await request.json();9 const { title, description, startTime, endTime, attendeeEmails = [] } = body;1011 if (!title || !startTime || !endTime) {12 return NextResponse.json(13 { error: 'title, startTime, and endTime are required' },14 { status: 400 }15 );16 }1718 const cookieStore = await cookies();19 const tokensRaw = cookieStore.get('google_tokens')?.value;2021 if (!tokensRaw) {22 return NextResponse.json({ error: 'Not authenticated with Google' }, { status: 401 });23 }2425 const tokens = JSON.parse(tokensRaw);2627 const oauth2Client = new google.auth.OAuth2(28 process.env.GOOGLE_CLIENT_ID,29 process.env.GOOGLE_CLIENT_SECRET,30 process.env.GOOGLE_REDIRECT_URI31 );3233 oauth2Client.setCredentials(tokens);3435 const calendar = google.calendar({ version: 'v3', auth: oauth2Client });3637 const attendees = attendeeEmails.map((email: string) => ({ email }));3839 const event = await calendar.events.insert({40 calendarId: 'primary',41 conferenceDataVersion: 1,42 sendNotifications: true,43 requestBody: {44 summary: title,45 description: description ?? '',46 start: { dateTime: startTime, timeZone: 'UTC' },47 end: { dateTime: endTime, timeZone: 'UTC' },48 attendees,49 conferenceData: {50 createRequest: {51 requestId: randomUUID(),52 conferenceSolutionKey: { type: 'hangoutsMeet' },53 },54 },55 },56 });5758 const meetLink = event.data.conferenceData?.entryPoints?.find(59 (ep) => ep.entryPointType === 'video'60 )?.uri ?? null;6162 return NextResponse.json({63 eventId: event.data.id,64 meetLink,65 htmlLink: event.data.htmlLink,66 });67}Pro tip: Each conferenceData createRequest must have a unique requestId (use randomUUID()). Google uses this to deduplicate requests — if you accidentally call the endpoint twice with the same requestId, Google returns the existing conference instead of creating a duplicate.
Expected result: POST /api/meetings/create with valid title, startTime, endTime returns a JSON object with meetLink (a meet.google.com URL), eventId, and htmlLink. The calendar event appears in Google Calendar with the Meet link attached.
Add Environment Variables in Vercel
Add Environment Variables in Vercel
Add your Google OAuth2 credentials to Vercel so they are available in your deployed API routes. In Vercel Dashboard → Settings → Environment Variables, add the following for Production, Preview, and Development scopes. GOOGLE_CLIENT_ID: the Client ID from your OAuth2 credentials in Google Cloud Console → APIs & Services → Credentials. This is used to identify your application to Google. GOOGLE_CLIENT_SECRET: the Client Secret. Never prefix with NEXT_PUBLIC_ — this must stay server-side. GOOGLE_REDIRECT_URI: the full callback URL. Use https://your-app.vercel.app/api/google/callback for Production and http://localhost:3000/api/google/callback for Development. This must match exactly what you registered in Google Cloud Console. For local development, add the same variables to .env.local. Ensure the development redirect URI (http://localhost:3000/api/google/callback) is also listed in your Google Cloud Console credentials. After adding variables, redeploy your app. Test the full flow: navigate to /api/google/auth, complete Google authorization, and then test /api/meetings/create with a sample POST body.
Pro tip: If you want to test meeting creation without going through OAuth2 each time, temporarily hardcode valid tokens in .env.local during development. Never commit tokens to Git — use the OAuth2 flow for all testing beyond your local machine.
Expected result: Vercel shows GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI in environment variables. The full OAuth flow completes successfully in the deployed app and meeting creation returns a valid Meet link.
Generate the Meeting Scheduler UI with V0
Generate the Meeting Scheduler UI with V0
With the API routes working, use V0 to generate the meeting scheduling interface. Describe the exact booking flow to V0: a date and time picker, an attendee email input, and a success state that displays the Meet link. V0 generates excellent form components with Tailwind CSS and shadcn/ui. Ask it to create a scheduling form that validates inputs before submitting (required fields, valid email formats, start time before end time), calls your /api/meetings/create endpoint, and shows the Meet link in a copyable display after success. For date and time pickers, V0 typically uses the shadcn/ui Calendar and TimePicker components or the react-day-picker library. Specify which you prefer, or let V0 choose — both produce clean interfaces. Consider asking V0 to add a 'Copy Link' button with clipboard API support next to the Meet link display. This is one of the most important UX elements in a meeting scheduler — users need to copy the Meet link to share it or add it to their own calendar. For complex scheduling features like availability checking (preventing double-booking), time zone handling for distributed teams, or integration with external calendars, RapidDev's team can help architect a more complete scheduling solution built on top of this foundation.
Create a meeting scheduler form with inputs for Meeting Title (text), Description (textarea, optional), Date (date picker), Start Time and End Time (time dropdowns in 30-minute increments), and Attendee Emails (tag input allowing multiple emails). A Schedule Meeting button submits the form. POST to /api/meetings/create. On success, show a confirmation card with the meeting title, date, time, a Google Meet link in a highlighted box with a Copy Link button, and an Add to Google Calendar link using the htmlLink from the response.
Paste this in V0 chat
Pro tip: Ask V0 to pre-fill the end time as start time plus 30 minutes whenever the user selects a start time. This small UX improvement significantly reduces the friction of scheduling meetings.
Expected result: Your app shows a complete meeting scheduling form. Filling out the form and clicking Schedule Meeting creates a Google Calendar event, returns a Meet link, and displays it in the confirmation state. The link works when pasted into a browser.
Common use cases
Customer Consultation Booking
A B2B SaaS or agency lets prospects book consultations directly from their website. V0 generates a booking form where the prospect enters their name, email, and preferred time slot. The API route creates a Google Calendar event with a Meet link and sends the link to both the prospect and the internal team.
Create a consultation booking form with fields for name, email, company name, and a time slot selector showing available 30-minute slots for the next 5 business days. A Submit button posts the form data to /api/meetings/create. After successful submission, show a confirmation screen with the Google Meet link in a copyable text field, the date and time, and a button to add to Google Calendar using a Google Calendar URL.
Copy this prompt to try it in V0
Job Interview Scheduler
An HR platform automatically generates Google Meet links for job interviews when a candidate reaches a certain stage in the hiring pipeline. V0 generates the interview scheduling interface in the recruiter dashboard, and the API creates the calendar event with the candidate and interviewer as attendees.
Build an interview scheduling panel that shows the candidate's name and the selected interview time. Include a Generate Meet Link button that POSTs to /api/interviews/schedule with candidateEmail, interviewerEmail, startTime, and duration. After the API responds, display the Meet link in a prominent card with a copy button, and show a calendar event summary with attendees listed.
Copy this prompt to try it in V0
Event Registration with Live Stream Link
A community platform or educational product hosts regular live sessions via Google Meet. V0 generates the event registration page, and when a user registers, the API creates a Calendar event (or retrieves an existing one) and returns the Meet link so the registrant can join the session at the scheduled time.
Create an event registration page showing event title, date, time, and description. Include a large Register button. When clicked, POST to /api/events/register with the user's email and the event ID. Show a success state with the Google Meet link, a countdown timer to the event, and an Add to Calendar button. If already registered, show the existing Meet link without creating a duplicate.
Copy this prompt to try it in V0
Troubleshooting
calendar.events.insert returns a response with no conferenceData or meetLink is null
Cause: The conferenceDataVersion parameter was not set to 1, or the createRequest in conferenceData was missing or malformed. Without conferenceDataVersion=1, Google ignores the conferenceData request and creates a plain calendar event without Meet.
Solution: Ensure your calendar.events.insert call includes conferenceDataVersion: 1 as a top-level parameter (not inside the requestBody) and that conferenceData.createRequest has a unique requestId and conferenceSolutionKey: { type: 'hangoutsMeet' }.
1// Correct structure — conferenceDataVersion is a query param, not in requestBody:2const event = await calendar.events.insert({3 calendarId: 'primary',4 conferenceDataVersion: 1, // <-- required at this level5 requestBody: {6 conferenceData: {7 createRequest: {8 requestId: randomUUID(), // <-- must be unique per request9 conferenceSolutionKey: { type: 'hangoutsMeet' },10 },11 },12 },13});OAuth2 authentication fails with 'invalid_grant' after working initially
Cause: The stored access token has expired and the refresh token refresh failed. This can happen if Google has revoked the token (user revoked access in their Google account settings), the refresh token was not stored after first login, or tokens were not updated after being refreshed.
Solution: Redirect users back to /api/google/auth to re-authorize. Store the new tokens returned by oauth2Client on the 'tokens' event listener and update them in your storage. Also add the access_type: 'offline' and prompt: 'consent' parameters to always receive a fresh refresh token.
1oauth2Client.on('tokens', (newTokens) => {2 // Store the updated tokens whenever they are refreshed3 if (newTokens.refresh_token) {4 // Update stored refresh token5 }6 // Always update the access token7});Google shows 'This app hasn't been verified' warning on the OAuth consent screen
Cause: Your Google Cloud app is not verified by Google and is requesting sensitive scopes (like calendar.events). This appears for external users during development and testing.
Solution: During development, add specific Google accounts as test users in the OAuth consent screen configuration. Only those accounts see the consent screen without the warning. For production apps used by external users, submit your app for Google verification — the process takes 1-4 weeks.
Calendar event is created but attendees do not receive email invitations
Cause: The sendNotifications parameter was not set to true, or the attendee email addresses are not valid Google accounts (non-Google email addresses may not receive Google Calendar invitations).
Solution: Set sendNotifications: true in your events.insert call. Note that invitations to non-Google email addresses depend on the attendees' calendar software — they may receive an ICS file instead of a Google Calendar invitation. For non-Google attendees, send a separate email with the Meet link.
Best practices
- Store Google OAuth2 tokens in a database linked to user accounts rather than cookies — this enables proper token refresh management and keeps users logged in across sessions
- Listen to the googleapis client 'tokens' event to capture refreshed access tokens and update your storage, preventing re-authentication prompts
- Use unique randomUUID() values for each conferenceData createRequest requestId to prevent Google from deduplicating your meeting creation requests
- Request only the calendar.events scope rather than the broader calendar scope — minimum permissions build user trust and reduce OAuth consent screen friction
- Validate time zone handling carefully — store and display times in UTC or store the user's time zone preference and convert before creating the event
- Add the meeting's htmlLink (Google Calendar event URL) to your confirmation UI alongside the Meet link so users can view and edit the event in Google Calendar
- For multi-tenant apps, store each user's Google tokens separately and use per-user OAuth2 clients to ensure meetings are created in the correct user's calendar
Alternatives
Zoom has a dedicated Meetings API that creates meeting links directly without requiring a calendar integration, making it simpler to generate on-demand meeting rooms.
Microsoft Teams is better suited for organizations in the Microsoft 365 ecosystem, using the Microsoft Graph API to create Teams meetings similar to this Google Calendar pattern.
Doodle specializes in group scheduling and meeting polls, which is better for finding common availability among multiple attendees rather than instantly creating a meeting link.
Frequently asked questions
Does Google Meet have its own API separate from Google Calendar?
Google does have a Google Meet REST API in preview (meet.googleapis.com) as of 2023, but its primary use case is reading meeting metadata, retrieving recordings, and accessing artifacts from past meetings — not creating new meetings. For creating Google Meet links programmatically, the Calendar API with conferenceDataVersion=1 remains the standard approach and is what the official Google documentation recommends.
Can I create Google Meet links without a calendar event?
Not through the standard Calendar API approach — every Meet link is associated with a calendar event. However, you can create the calendar event with no attendees and a title that is hidden from the organizer's view, making the event invisible in practice while still generating the Meet link. The Google Meet app also allows ad-hoc meetings at meet.google.com/new, but this cannot be automated via API.
Do my users need Google accounts to join meetings created via API?
No. Anyone with the Meet link can join a Google Meet meeting — they do not need a Google account as a guest, though they may need to request admission from the meeting host if the host has admission controls enabled. Calendar invitations are sent to attendees regardless of whether they have Google accounts, though non-Google calendar apps receive ICS files.
How do I handle time zones in meeting scheduling?
Always convert times to UTC before passing them to the Calendar API, or use the timeZone parameter in the event's start and end objects to specify the IANA time zone identifier (e.g., 'America/New_York'). Store the user's preferred time zone in your app and apply it when constructing event times. Display times back to users in their local time zone using Intl.DateTimeFormat.
Can V0 generate the entire meeting scheduler including calendar integration?
V0 can generate the scheduling form UI, the API route code structure, and the confirmation display components. However, it cannot create your Google Cloud project, enable APIs, or complete the OAuth2 consent screen configuration — those steps require manual work. V0 is best used for the UI and route scaffolding, which you then wire to your actual Google credentials.
What happens if I need to cancel or reschedule a meeting?
Use the Google Calendar API's events.delete() to cancel a meeting (the Meet link becomes invalid) or events.patch() to update the event's start and end times for rescheduling. The Meet link remains the same when you update the event time. Send updated invitations by setting sendNotifications: true on the patch request.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation