Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Vimeo

To integrate Lovable with Vimeo, create a Supabase Edge Function that proxies Vimeo API calls using OAuth2 access tokens stored in Cloud → Secrets. Embed videos using the Vimeo Player SDK directly in your React components, and use tus-based upload for large files. Lovable's chat can generate video library UIs, showcase pages, and analytics dashboards once the Edge Function proxy is in place.

What you'll learn

  • How to create a Vimeo API application and obtain OAuth2 credentials
  • How to proxy Vimeo API calls through a Supabase Edge Function with proper authentication
  • How to embed Vimeo videos in React using the Vimeo Player SDK
  • How to implement tus-based resumable video uploads through Lovable
  • How to build video library and showcase UIs using Lovable's chat prompts
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate15 min read45 minutesSocialMarch 2026RapidDev Engineering Team
TL;DR

To integrate Lovable with Vimeo, create a Supabase Edge Function that proxies Vimeo API calls using OAuth2 access tokens stored in Cloud → Secrets. Embed videos using the Vimeo Player SDK directly in your React components, and use tus-based upload for large files. Lovable's chat can generate video library UIs, showcase pages, and analytics dashboards once the Edge Function proxy is in place.

Build professional video libraries and showcase pages with the Vimeo API

Vimeo's API gives you full programmatic control over your video library: upload new videos, organize them into folders and showcases, retrieve transcoding status, manage privacy settings, and pull analytics data. The API uses OAuth2 Bearer tokens and returns JSON — it is well-documented, consistent, and designed for developers building video-centric applications.

The integration splits into two parts. Video management (listing videos, creating uploads, modifying settings, fetching analytics) must go through an Edge Function because it requires your OAuth2 access token — a secret that cannot live in browser code. Video embedding works differently: the Vimeo Player SDK is a public JavaScript library you load directly in React components using the video's ID or URL. The player handles privacy controls internally — if a video is set to 'only on this domain', the embed works on your deployed app URL without any server-side involvement.

Vimeo excels for professional video workflows: client proofing, course content delivery, portfolio showcases, and product demo libraries. Its tus-based upload protocol supports resumable uploads for large files, making it reliable for high-resolution video without timeout issues. Vimeo is distinct from Spotify-API — Vimeo hosts your own video content, while Spotify API provides access to a licensed music catalog you do not own.

Integration method

Edge Function Integration

Vimeo uses OAuth2 for its API and exposes endpoints for managing videos, folders, showcases, and analytics. Authenticated API calls are proxied through a Supabase Edge Function to keep OAuth tokens server-side. Video embedding uses Vimeo's Player SDK loaded directly in React, which does not require authentication — only the management API calls need the Edge Function proxy.

Prerequisites

  • A Lovable account with a project that has Lovable Cloud enabled
  • A Vimeo account — a Basic (free) or paid plan depending on your storage and privacy needs
  • A Vimeo API application registered at developer.vimeo.com — you need the client identifier and client secret
  • A Vimeo OAuth2 personal access token with the scopes: public, private, video_files, and create for upload
  • Familiarity with how Vimeo organizes content: videos, folders, and showcases are the three main organizational structures

Step-by-step guide

1

Create a Vimeo API application and generate an access token

Navigate to developer.vimeo.com in your browser. Click 'Create an app' and fill in the app name (e.g., 'My Lovable Portfolio'), description, and your app's URL. For the redirect URI, enter your deployed Lovable app URL — for example, https://your-app.lovable.app/auth/vimeo/callback. Click 'Create app'. Once created, you will see your app's dashboard with the Client Identifier and Client Secret. Scroll down to the 'Personal Access Tokens' section. Click 'Generate a personal access token'. Select the scopes your app needs: 'public' for reading public video data, 'private' for accessing private videos, 'video_files' for getting download links, and 'create' for uploading new videos. Click 'Generate' and copy the token immediately — it is only shown once. For apps where end users log in with their own Vimeo accounts to manage their own videos, you will need to implement the full OAuth2 authorization code flow. But for the most common Lovable use case — a developer building a portfolio or client platform using their own Vimeo account — the personal access token is simpler and sufficient. The token does not expire unless you revoke it manually. Note your API rate limits: Vimeo Basic accounts are limited to 250 API requests per hour. Vimeo Pro and above have higher limits. For production apps with many users, cache API responses in Supabase to stay well within limits.

Pro tip: Select only the OAuth scopes your app actually needs. Requesting 'delete' or 'interact' scopes when your app only needs to display videos creates unnecessary security exposure if your token is ever compromised.

Expected result: You have a Vimeo Client Identifier, Client Secret, and a personal access token. The access token appears in your app's Personal Access Tokens list in the Vimeo developer portal.

2

Store Vimeo credentials in Cloud → Secrets

Open your Lovable project and click the '+' icon at the top of the editor next to the Preview label to open the Cloud panel. Click the Secrets tab, then 'Add new secret'. Add the following secrets: - Name: VIMEO_ACCESS_TOKEN — Value: your personal access token from Step 1 - Name: VIMEO_CLIENT_ID — Value: your Client Identifier - Name: VIMEO_CLIENT_SECRET — Value: your Client Secret These three secrets give your Edge Function full ability to authenticate with the Vimeo API and, if needed, generate new tokens using the OAuth2 flow. The VIMEO_ACCESS_TOKEN is the primary credential used for API calls. The CLIENT_ID and CLIENT_SECRET are stored for use in any token refresh or OAuth2 authorization code flows you implement later. Vimeo access tokens are long-lived (they do not expire on a schedule) but can be revoked at any time from the Vimeo developer portal. Lovable's security system blocks approximately 1,200 hardcoded API keys per day, but the correct approach is to always use the Secrets panel — never paste tokens into Lovable's chat or into source code. Verify the secrets appear in the panel with masked values before proceeding. The exact secret names used here must match the Deno.env.get() calls in the Edge Function exactly — a typo in either place causes a runtime error that is easy to miss until you test the function.

Expected result: VIMEO_ACCESS_TOKEN, VIMEO_CLIENT_ID, and VIMEO_CLIENT_SECRET appear in Cloud → Secrets with masked values.

3

Create the Vimeo API proxy Edge Function

Create an Edge Function that proxies requests to Vimeo's REST API. The function accepts a Vimeo API path (like /me/videos or /videos/123456) and optional query parameters from the frontend, forwards the request to https://api.vimeo.com with your OAuth token, and returns the JSON response. In Lovable's chat, paste the prompt below to generate and deploy the function. After Lovable creates it, navigate to Cloud → Edge Functions to confirm it appears. The function URL will be https://[your-project-ref].supabase.co/functions/v1/vimeo-api. The Edge Function in the code block below handles both GET requests (for fetching video lists, showcase details, and analytics) and POST requests (for creating new videos or updating metadata). It reads the API path from the request URL's query string — the frontend calls /vimeo-api?path=/me/videos, and the function appends that path to the Vimeo base URL.

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/vimeo-api/index.ts. It should accept GET and POST requests. Read the Vimeo API path from a 'path' query parameter (e.g., /me/videos). Forward the request to https://api.vimeo.com{path} with the Authorization: bearer header using VIMEO_ACCESS_TOKEN from Deno.env. Include CORS headers and return the Vimeo API response as JSON.

Paste this in Lovable chat

supabase/functions/vimeo-api/index.ts
1// supabase/functions/vimeo-api/index.ts
2const VIMEO_BASE_URL = 'https://api.vimeo.com';
3
4Deno.serve(async (req) => {
5 if (req.method === 'OPTIONS') {
6 return new Response(null, {
7 headers: {
8 'Access-Control-Allow-Origin': '*',
9 'Access-Control-Allow-Methods': 'GET, POST, PATCH, DELETE, OPTIONS',
10 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
11 },
12 });
13 }
14
15 const accessToken = Deno.env.get('VIMEO_ACCESS_TOKEN');
16 if (!accessToken) {
17 return new Response(JSON.stringify({ error: 'Vimeo access token not configured' }), {
18 status: 500,
19 headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
20 });
21 }
22
23 const url = new URL(req.url);
24 const apiPath = url.searchParams.get('path') || '/me/videos';
25 const queryString = url.searchParams.get('query') || '';
26 const vimeoUrl = `${VIMEO_BASE_URL}${apiPath}${queryString ? '?' + queryString : ''}`;
27
28 const requestInit: RequestInit = {
29 method: req.method,
30 headers: {
31 'Authorization': `bearer ${accessToken}`,
32 'Content-Type': 'application/json',
33 'Accept': 'application/vnd.vimeo.*+json;version=3.4',
34 },
35 };
36
37 if (req.method === 'POST' || req.method === 'PATCH') {
38 requestInit.body = await req.text();
39 }
40
41 const vimeoResponse = await fetch(vimeoUrl, requestInit);
42 const data = await vimeoResponse.json();
43
44 return new Response(JSON.stringify(data), {
45 status: vimeoResponse.status,
46 headers: {
47 'Content-Type': 'application/json',
48 'Access-Control-Allow-Origin': '*',
49 },
50 });
51});

Expected result: The vimeo-api Edge Function is deployed and listed in Cloud → Edge Functions. Calling it with ?path=/me/videos returns your Vimeo video library as JSON.

4

Embed Vimeo videos using the Player SDK in React

Video embedding in React does not require any server-side calls — the Vimeo Player SDK loads directly in the browser and communicates with Vimeo's CDN. You can embed a video by ID, by URL, or by fetching an oEmbed URL from Vimeo's public oEmbed endpoint. Ask Lovable to install the @vimeo/player npm package and create a reusable VideoPlayer component. This component accepts a Vimeo video ID or URL as a prop, initializes the Vimeo Player in a div ref, and exposes player events (play, pause, ended, timeupdate) via callbacks. The Player SDK is particularly powerful for course platforms because it lets you track exactly how much of each video a user has watched. Listen to the 'timeupdate' event to record progress, and the 'ended' event to mark a lesson as complete. Store these events in Supabase so users can resume where they left off across devices. For domain-restricted videos (Vimeo's 'Only on my domain' privacy setting), the player will automatically block playback on unauthorized domains. Set your deployed app domain in the Vimeo video settings under Privacy → Embed → Specific domains. Test on your deployed URL rather than the Lovable preview, as the preview runs on a different domain that will not be on your allowlist.

Lovable Prompt

Install the @vimeo/player npm package and create a reusable VimeoPlayer component that accepts a videoId prop (string). Use a useRef div as the player container and initialize the Vimeo Player in a useEffect. Expose onEnded and onProgress callback props. Style it to be 16:9 aspect ratio with rounded corners and a subtle shadow.

Paste this in Lovable chat

src/components/VimeoPlayer.tsx
1// src/components/VimeoPlayer.tsx
2import { useEffect, useRef } from 'react';
3import Player from '@vimeo/player';
4
5interface VimeoPlayerProps {
6 videoId: string;
7 onEnded?: () => void;
8 onProgress?: (data: { seconds: number; percent: number }) => void;
9 className?: string;
10}
11
12export function VimeoPlayer({ videoId, onEnded, onProgress, className }: VimeoPlayerProps) {
13 const containerRef = useRef<HTMLDivElement>(null);
14 const playerRef = useRef<Player | null>(null);
15
16 useEffect(() => {
17 if (!containerRef.current) return;
18
19 const player = new Player(containerRef.current, {
20 id: parseInt(videoId, 10),
21 responsive: true,
22 dnt: false,
23 });
24
25 playerRef.current = player;
26
27 if (onEnded) {
28 player.on('ended', onEnded);
29 }
30
31 if (onProgress) {
32 player.on('timeupdate', (data) => {
33 onProgress({ seconds: data.seconds, percent: data.percent });
34 });
35 }
36
37 return () => {
38 player.destroy();
39 };
40 }, [videoId]);
41
42 return (
43 <div
44 ref={containerRef}
45 className={`aspect-video rounded-lg overflow-hidden shadow-md ${className || ''}`}
46 />
47 );
48}

Pro tip: The Vimeo Player SDK's responsive: true option makes the player fill its container width while maintaining the correct aspect ratio. Wrap the player in an aspect-video Tailwind class for a clean 16:9 layout without any hardcoded pixel dimensions.

Expected result: The VimeoPlayer component renders Vimeo videos embedded in the app. The player controls are visible and functional. The onEnded callback fires when playback completes, and onProgress fires during playback with the current position.

5

Implement tus resumable video uploads

For uploading video files to Vimeo, the standard approach of posting directly to an API endpoint does not work well for large files — it times out and fails without any progress reporting. Vimeo supports the tus upload protocol, which enables resumable uploads that automatically recover from network interruptions. For a 500 MB video file, this is the difference between a reliable upload and a frustrating experience. The upload flow has two steps: first, create an upload slot on Vimeo via the API (which returns an upload URL), then upload the file directly from the browser to that URL using the tus client. The first step (creating the upload slot) requires your OAuth token, so it goes through the Edge Function. The second step (the actual file transfer) goes directly from the browser to Vimeo's upload CDN using the upload URL returned in step one — no token required at this stage. Ask Lovable to install the tus-js-client npm package and create an upload component. The component should show a file picker, a progress bar, and handle errors gracefully. After the upload completes, poll the Vimeo API (via your Edge Function) for the video's transcode status until it becomes available, then store the video ID in Supabase. For complex enterprise upload workflows with chunked uploads, retry logic, and multi-user queuing, RapidDev's team can help design the full architecture including Supabase queuing tables and Edge Function orchestration.

Lovable Prompt

Install tus-js-client. Create a VideoUpload component with a file input for video files, a progress bar, and upload status messages. When a file is selected: (1) call the vimeo-api Edge Function with a POST to /me/videos to create an upload slot and get the upload URL, (2) use tus.Upload to upload the file directly to that URL, (3) on completion, call the Edge Function to get the video details and save the video ID to a Supabase table called 'videos' with columns: vimeo_id, title, status, user_id.

Paste this in Lovable chat

Expected result: The upload component shows a progress bar during upload and updates the Supabase videos table when complete. Uploads of large files resume automatically after network interruptions. The Vimeo dashboard shows the newly uploaded video undergoing transcoding.

Common use cases

Video portfolio with private showcase sharing

Build a video portfolio that pulls your Vimeo library via the API, displays videos in a grid, and lets clients view private showcase links you control from your Lovable dashboard. Videos are embedded using the Vimeo Player SDK with domain-level privacy so they only play on your app.

Lovable Prompt

Create a video portfolio page that fetches my Vimeo videos from the vimeo-api Edge Function at /me/videos and displays them in a responsive grid. Each card should show the video thumbnail, title, duration, and view count. Clicking a card opens a modal with the embedded Vimeo player using the @vimeo/player package.

Copy this prompt to try it in Lovable

Course content library with progress tracking

Build a corporate training platform where videos are organized into Vimeo showcases (courses) and users' progress is tracked in Supabase. The Vimeo Player SDK fires events when users complete a video, which the app records to show completion status on the course overview.

Lovable Prompt

Build a course library page that fetches showcases from my Vimeo account via the vimeo-api Edge Function and displays them as course cards. When a user clicks into a course, show the individual videos as lessons. Use the Vimeo Player SDK to embed each video and fire an event to the Supabase database when the player triggers the 'ended' event, recording that the user completed that lesson.

Copy this prompt to try it in Lovable

Client video delivery platform with upload and approval

Create a platform where video producers upload deliverables directly to Vimeo via a tus upload flow, and clients receive a private link to review and approve. Approval status is tracked in Supabase, and Vimeo's privacy settings prevent unauthorized sharing.

Lovable Prompt

Create an upload page that lets users select a video file and upload it directly to Vimeo using tus resumable upload. Show a progress bar during upload. Once complete, call the vimeo-api Edge Function to set the video privacy to 'unlisted' and save the Vimeo video ID and share URL to a Supabase table called 'deliverables'.

Copy this prompt to try it in Lovable

Troubleshooting

API calls return 401 Unauthorized with message 'You must be authenticated to access this endpoint'

Cause: The VIMEO_ACCESS_TOKEN secret is either missing, incorrectly named, or the token was revoked in the Vimeo developer portal.

Solution: Check Cloud → Secrets and confirm VIMEO_ACCESS_TOKEN exists with the correct value. Then go to developer.vimeo.com, open your app, and verify the personal access token is still listed and not revoked. If you need to regenerate a token, create a new one, update the secret in Cloud → Secrets, and redeploy the Edge Function by making a trivial change in Lovable's chat.

Embedded Vimeo player shows 'This video cannot be played here' or a privacy error

Cause: The video is set to domain-restricted privacy ('Only on my domain') but your app's domain is not on Vimeo's allowed domains list for that video, or you are testing in Lovable's preview (which uses a different domain).

Solution: Go to vimeo.com, open the video settings, navigate to Privacy → Where can this be embedded, and add your deployed app domain (e.g., your-app.lovable.app). If you are testing in the Lovable preview, note that the preview runs on a subdomain of lovable.app that differs from your deployed URL — always test domain-restricted embeds on the deployed app, not in the editor preview.

tus upload fails with 'Cannot read properties of undefined' or gets stuck at 0%

Cause: The upload URL returned by Vimeo's /me/videos API was not extracted correctly from the response, or the tus client version is incompatible with how the Edge Function returns the upload link.

Solution: Log the full response from the POST to /me/videos in your Edge Function. The upload URL is at response.upload.upload_link in Vimeo's API response — not at the top level. Verify that your Edge Function correctly returns this nested field to the frontend and that the tus client is initialized with the exact upload_link string.

typescript
1// Correct extraction of Vimeo upload link
2const vimeoResponse = await fetch('https://api.vimeo.com/me/videos', {
3 method: 'POST',
4 headers: { 'Authorization': `bearer ${token}`, 'Content-Type': 'application/json' },
5 body: JSON.stringify({ upload: { approach: 'tus', size: fileSize }, name: fileName }),
6});
7const data = await vimeoResponse.json();
8const uploadUrl = data.upload?.upload_link; // nested under 'upload'

Edge Function returns 'Vimeo access token not configured' error

Cause: The VIMEO_ACCESS_TOKEN secret name in Cloud → Secrets does not exactly match the string used in Deno.env.get() inside the Edge Function.

Solution: Go to Cloud → Secrets and verify the exact name of the secret. Open the Edge Function code in the Code panel and find the Deno.env.get() call. The string inside the parentheses must be an exact character-for-character match, including capitalization and underscores. Update whichever is incorrect — either rename the secret in Cloud → Secrets or update the Deno.env.get() call in the function code.

Best practices

  • Store all Vimeo OAuth credentials in Cloud → Secrets and access them via Deno.env.get() — never hardcode tokens in Edge Function code or React components
  • Use the Vimeo Player SDK's responsive: true option and wrap the player container in an aspect-video CSS class to maintain 16:9 ratio across all screen sizes
  • Cache Vimeo API responses for video library listings in Supabase — Vimeo Basic accounts have 250 API requests per hour, and caching prevents you from hitting this limit on popular pages
  • Use tus-js-client for all video uploads to enable resumable uploads; avoid the standard multipart approach for files larger than 50 MB
  • Set video privacy to 'Only on my domain' in Vimeo and add your deployed app domain to prevent videos from being embedded on other sites
  • Listen to the Vimeo Player SDK's 'ended' and 'timeupdate' events to track viewing progress and store completion data in Supabase for course-style applications
  • Test video embeds on your deployed Lovable app URL, not in the editor preview — domain-restricted videos and some player behaviors differ between the preview iframe and the live deployment

Alternatives

Frequently asked questions

Do I need a paid Vimeo plan to use the API?

The Vimeo API is available on all plans including the free Basic plan, but the Basic plan has significant restrictions: 500 MB of total storage, 250 API requests per hour, and no access to advanced privacy features. For production applications, Vimeo Starter ($12/month) or above is strongly recommended for more storage, higher API rate limits, and privacy controls like domain-restricted embedding.

Can the Vimeo Player embed work in Lovable's preview panel?

Standard Vimeo embeds (public videos with no domain restrictions) will work in the Lovable preview panel. Domain-restricted videos will not, because the preview runs on a Lovable-owned subdomain that is not on your Vimeo allowed-domains list. For testing domain-restricted embeds, always use your deployed app URL — the preview is sufficient for verifying that the player loads and basic controls work.

How do I get the Vimeo video ID for embedding?

The Vimeo video ID is the numeric portion of the video URL. For a video at vimeo.com/123456789, the ID is 123456789. You can also get IDs programmatically by fetching /me/videos from the Vimeo API via your Edge Function — each video object includes a uri field like /videos/123456789 from which you extract the numeric ID. Store video IDs in Supabase rather than re-fetching them from the API on every page load.

Why does Vimeo use 'bearer' (lowercase) in the Authorization header?

This is a quirk of Vimeo's API. Standard OAuth2 specifies 'Bearer' (capitalized), but Vimeo's API documentation and implementation uses lowercase 'bearer'. Both forms are technically accepted by Vimeo's servers, but using lowercase matches their documentation examples and avoids potential issues. The Edge Function code in this tutorial uses lowercase 'bearer' to match Vimeo's convention.

Can I give end users of my Lovable app the ability to connect their own Vimeo accounts?

Yes, but it requires implementing Vimeo's OAuth2 authorization code flow. You would create an Edge Function to handle the OAuth redirect and token exchange, store each user's Vimeo access token in a Supabase table linked to their user ID, and then use that user-specific token when making API calls on their behalf. This is more complex than the personal token approach described in this tutorial. For multi-user Vimeo integrations, start with the personal token pattern and add user-level OAuth once your core functionality is working.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.