To integrate LinkedIn Learning with V0 by Vercel, use iframe embeds for individual courses or implement SSO for organizational access. LinkedIn Learning has no general public API for content browsing — the integration focuses on embedding course players, linking to catalog content, and using LinkedIn's Learning API for enterprise SSO-based completions tracking.
Embed LinkedIn Learning Content and Build Learning Portals with V0
LinkedIn Learning (the rebranded Lynda.com) is the professional learning platform included with LinkedIn Premium and available as an enterprise subscription for organizations. Unlike platforms like Coursera or Udemy, LinkedIn Learning does not offer a public API for browsing or accessing course content — all course viewing requires an active subscription. However, there are practical integration patterns that work within these constraints for building learning portals and team development dashboards.
For individual courses, LinkedIn Learning provides shareable embed codes that work as iframes. Any course that the account owner has access to can be embedded on a webpage with a standard HTML iframe tag. This approach requires no API credentials and works for creating curated learning pages that link employees or customers to specific courses. The embedded player includes LinkedIn Learning branding and handles authentication by redirecting to LinkedIn login when the viewer clicks to play.
For enterprise customers with LinkedIn Learning organizational licenses, the LinkedIn Learning API provides richer capabilities: searching the course catalog, tracking completion status for your organization's learners, reporting on learning activity, and integrating with your LMS through xAPI/SCORM-compatible exports. This API requires OAuth2 credentials from a LinkedIn app with Learning API access, which is available to enterprise customers under their LinkedIn Learning agreement.
Integration method
LinkedIn Learning integrates with V0-generated Next.js apps primarily through iframe embeds for individual courses and API routes for enterprise features. LinkedIn Learning does not offer a public content browsing API — course content requires an active LinkedIn Learning subscription. For organizations with LinkedIn Learning licenses, the Learning API enables SSO-based authentication, completion tracking, and learning activity reporting through API routes that call the LinkedIn API with OAuth2 credentials.
Prerequisites
- A LinkedIn Learning account — either a personal LinkedIn Premium subscription for iframe embeds, or a LinkedIn Learning enterprise license for API access
- For enterprise API access: LinkedIn app credentials from linkedin.com/developers with the Learning API scope enabled (requires enterprise LinkedIn Learning agreement)
- For iframe embeds: the embed code or URL for specific courses you want to include — found on the course page under Share → Embed
- A V0 account at v0.dev and a Vercel account for deploying your learning portal
- Optionally: a database (Supabase, Neon) for storing course metadata, completion records, and user progress if building beyond simple embed display
Step-by-step guide
Generate the Learning Portal UI with V0
Generate the Learning Portal UI with V0
Open V0 at v0.dev and describe the learning portal interface you want to build. For a LinkedIn Learning integration, the UI options range from a simple embedded course player (a single iframe in a card) to a full learning management dashboard with progress tracking, course catalogs, and team activity views. For iframe-based integrations, the key component is a CourseCard that accepts a course title, duration, skill level, description, and an embedUrl property. The embedUrl is the LinkedIn Learning embed URL for that course — it follows the pattern https://www.linkedin.com/learning/embed/{course-slug} and is included in the share embed code from each course page. The card renders the iframe inside a modal or expandable panel to avoid overwhelming the page with multiple video players. For a curated catalog approach, ask V0 to generate a grid of course cards that load from your API route (which reads from a database where you've stored course metadata). This gives you full control over which courses appear and lets you add custom metadata like internal skill tags, required vs. optional labels, and role-based filtering that LinkedIn Learning itself doesn't provide in its standard interface. After generating your UI in V0, push to GitHub via V0's Git panel before setting up the backend routes.
Create a learning catalog page with a filter bar (All / Beginner / Intermediate / Advanced) and a grid of course cards. Each card shows a thumbnail image (URL from the course data), course title, instructor name, duration (e.g., '2h 15m'), skill level badge, and a View Course button. Clicking View Course opens a modal with an iframe showing the LinkedIn Learning embedded player (from embedUrl in the course data) plus a full course description and skills taught section. Include a search input above the grid. Load courses from /api/learning/courses. Use a modern e-learning platform style.
Paste this in V0 chat
Pro tip: LinkedIn Learning embed iframes require allow='fullscreen' and have sandbox restrictions. Use the exact embed code from the LinkedIn Learning course share dialog rather than constructing the URL manually — LinkedIn may change URL patterns, and the share dialog always provides the current correct format.
Expected result: A learning catalog renders in V0's preview with course cards, filter controls, and a modal with iframe player. The component loads course data from /api/learning/courses and displays embedded LinkedIn Learning players.
Build Your Course Catalog API with a Database
Build Your Course Catalog API with a Database
Since LinkedIn Learning does not offer a public content API, you'll store your curated course catalog in your own database and serve it through a Next.js API route. This approach gives you complete control over which courses to feature, how to categorize them, and what metadata to attach (like internal skill mappings, role requirements, or team-specific recommendations). Set up a courses table in your database with columns for id, title, instructor, duration_minutes, skill_level, description, linkedin_url, embed_url, thumbnail_url, skill_tags, and is_featured. Populate this table manually by browsing LinkedIn Learning and copying the relevant course URLs and metadata. The embed URL follows the pattern https://www.linkedin.com/learning/embed/{course-slug}?u={organization_id} for enterprise accounts (the u parameter ties the embed to your organization's license), or https://www.linkedin.com/learning/embed/{course-slug} for personal premium access. Create an API route at app/api/learning/courses/route.ts that queries your database and returns the course catalog as JSON. Add query parameter support for filtering by skill_level and searching by title. If you're using Supabase, the query is straightforward using the Supabase JavaScript client with .eq('skill_level', level) and .ilike('title', '%{search}%') filters. For tracking completions, create a user_completions table linking user IDs to course IDs with a completed_at timestamp. Add a POST endpoint at /api/learning/mark-complete that records when a user marks a course complete.
1// app/api/learning/courses/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { createClient } from '@supabase/supabase-js';45const supabase = createClient(6 process.env.NEXT_PUBLIC_SUPABASE_URL!,7 process.env.SUPABASE_SERVICE_ROLE_KEY!8);910export async function GET(request: NextRequest) {11 const { searchParams } = new URL(request.url);12 const skillLevel = searchParams.get('level');13 const search = searchParams.get('q');14 const track = searchParams.get('track');1516 let query = supabase17 .from('courses')18 .select('id, title, instructor, duration_minutes, skill_level, description, embed_url, thumbnail_url, skill_tags, track')19 .order('is_featured', { ascending: false })20 .order('title');2122 if (skillLevel && skillLevel !== 'all') {23 query = query.eq('skill_level', skillLevel);24 }2526 if (track) {27 query = query.eq('track', track);28 }2930 if (search) {31 query = query.ilike('title', `%${search}%`);32 }3334 const { data, error } = await query;3536 if (error) {37 return NextResponse.json({ error: error.message }, { status: 500 });38 }3940 return NextResponse.json({ courses: data ?? [] });41}Pro tip: Thumbnail images from LinkedIn Learning course pages require a LinkedIn account to view. To avoid broken images in your portal, download thumbnails and store them in your own storage (Supabase Storage, Vercel Blob, or AWS S3) rather than linking to LinkedIn's CDN directly.
Expected result: GET /api/learning/courses returns your curated course catalog from the database with filtering support. POST /api/learning/mark-complete records course completions for progress tracking.
Implement LinkedIn Learning API for Enterprise Tracking (Optional)
Implement LinkedIn Learning API for Enterprise Tracking (Optional)
If your organization has a LinkedIn Learning enterprise subscription, you can use the LinkedIn Learning API to fetch real completion data, search the official course catalog, and track organizational learning activity. This is an enterprise-only feature — contact your LinkedIn account manager to enable API access on your enterprise agreement. LinkedIn Learning API access uses standard LinkedIn OAuth2 through your LinkedIn app at linkedin.com/developers. You need the r_learning_classifications and r_lms_learner_history scopes (available only to enterprise accounts). The authorization flow is a standard OAuth2 authorization code flow — users authorize your app, you receive an authorization code, exchange it for access and refresh tokens, and store them in your database per user. Once authenticated, the LinkedIn Learning API endpoint at https://api.linkedin.com/v2/learningAssets returns course metadata including title, description, duration, skills, and difficulty level. The learnerActivityReport endpoint returns completion status and time spent for authenticated learners in your organization. These API calls happen in your Next.js API routes using the user's stored access token in the Authorization: Bearer header. For most V0-built apps, the database-backed catalog approach from the previous step is sufficient. The LinkedIn Learning API is primarily valuable when you need real-time completion syncing across a large organization or integration with your existing HR/LMS systems.
Add a My Progress section below the course catalog showing completed courses (fetched from /api/learning/my-progress) as a list with completion dates and a green checkmark. Show a circular progress indicator with the percentage of required courses completed. Add a 'Mark as Complete' button on each course card that calls POST /api/learning/mark-complete with the course id and shows a success toast when confirmed.
Paste this in V0 chat
1// app/api/learning/mark-complete/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { createClient } from '@supabase/supabase-js';45const supabase = createClient(6 process.env.NEXT_PUBLIC_SUPABASE_URL!,7 process.env.SUPABASE_SERVICE_ROLE_KEY!8);910export async function POST(request: NextRequest) {11 let body: { courseId: string; userId: string };1213 try {14 body = await request.json();15 } catch {16 return NextResponse.json({ error: 'Invalid request body' }, { status: 400 });17 }1819 const { courseId, userId } = body;2021 if (!courseId || !userId) {22 return NextResponse.json(23 { error: 'courseId and userId are required' },24 { status: 400 }25 );26 }2728 const { error } = await supabase29 .from('user_completions')30 .upsert(31 { course_id: courseId, user_id: userId, completed_at: new Date().toISOString() },32 { onConflict: 'course_id,user_id' }33 );3435 if (error) {36 return NextResponse.json({ error: error.message }, { status: 500 });37 }3839 return NextResponse.json({ success: true, completedAt: new Date().toISOString() });40}Pro tip: Use upsert instead of insert for completion records so that re-marking a course as complete updates the completed_at timestamp rather than creating duplicate records.
Expected result: Clicking 'Mark as Complete' on a course records the completion in the database and reflects in the user's progress section. The My Progress section shows accurately which courses have been completed.
Add Environment Variables and Deploy
Add Environment Variables and Deploy
Push your code to GitHub and configure your environment variables in Vercel. For the database-backed approach using Supabase, add NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY to Vercel. The SUPABASE_SERVICE_ROLE_KEY must not have the NEXT_PUBLIC_ prefix — it's a server-side secret that bypasses Supabase's row-level security and must only be used in API routes. The NEXT_PUBLIC_SUPABASE_URL is safe to expose as it's just the project URL. For the LinkedIn Learning enterprise API (if applicable), add LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET to Vercel, along with any stored access and refresh tokens if using a shared service account rather than per-user OAuth. After adding variables, click Redeploy in Vercel's Deployments tab. Test the deployed app by loading the course catalog (verify database-backed courses appear), clicking View Course (verify the iframe player loads), and marking a course complete (verify the database records the completion). If the iframe player shows a 'Sign in to LinkedIn' prompt, the embed URL may require the organization's LinkedIn ID parameter or the viewer needs an active LinkedIn Premium subscription.
Pro tip: LinkedIn Learning iframes may be blocked by browser content security policies if your Next.js app sets strict CSP headers. Add frame-src https://www.linkedin.com to your Content-Security-Policy header in next.config.ts to allow LinkedIn Learning iframes to load.
Expected result: The deployed Vercel app shows a working learning portal with course catalog, embedded LinkedIn Learning iframes, and functional completion tracking. The Supabase service role key is never visible in browser network requests.
Common use cases
Team Learning Resource Hub
Build an internal learning portal that curates LinkedIn Learning courses for different roles in your organization. Store course URLs and metadata in your own database, display a browsable catalog with skill tags, and embed course players directly in the portal for a seamless learning experience.
Create an internal learning hub with a sidebar navigation showing learning tracks (Engineering, Design, Leadership, Marketing). Each track shows a grid of course cards with course title, duration, skill level badge (Beginner/Intermediate/Advanced), and a preview thumbnail. Clicking a course card opens an expanded view with an embedded iframe player and a course description. Include a search bar that filters courses by title. Data loaded from /api/learning/courses (your custom database). Use a clean educational platform style with indigo as the primary color.
Copy this prompt to try it in V0
Employee Development Dashboard
For organizations with LinkedIn Learning enterprise access, show team learning activity including courses started, completed, and time spent learning. Display individual team member progress and surface recommended courses based on role or skill gaps.
Build a team learning dashboard with a summary section showing total courses completed this month, total learning hours, and most popular course. Below, show a leaderboard table with team members' names, courses completed, and learning hours this quarter. Add a Recommended Courses section with 3-4 course cards based on team skill gaps. Include a date filter for this week / this month / this quarter. Data from /api/learning/team-progress. Use a motivating, achievement-oriented design.
Copy this prompt to try it in V0
Onboarding Learning Path
Curate a sequential onboarding curriculum using LinkedIn Learning courses embedded in a step-by-step learning path. New employees follow a defined sequence of courses with checkboxes to mark completion, and managers see overall onboarding progress per team member.
Design an onboarding learning path page with numbered steps (Week 1: Company Culture, Week 2: Tools & Processes, Week 3: Role-Specific Skills). Each step contains 2-3 course cards with an embedded LinkedIn Learning iframe, estimated time, and a Complete button that calls /api/learning/mark-complete with the courseId. Show a progress bar at the top indicating overall onboarding completion percentage. Mark completed courses with a green checkmark. Use a friendly, welcoming onboarding style.
Copy this prompt to try it in V0
Troubleshooting
LinkedIn Learning iframe shows 'Sign in' prompt instead of the course
Cause: The viewer doesn't have a LinkedIn Learning subscription, the embed URL is missing the organization ID parameter, or the browser is blocking the third-party cookie that LinkedIn uses for authentication.
Solution: For enterprise embeds, ensure the embed URL includes ?u={your_organization_id} — the organization ID is found in your LinkedIn Learning admin settings. For personal premium users, the viewer must be signed into LinkedIn in the same browser. As a fallback, link to the course on LinkedIn Learning rather than embedding if the iframe approach is unreliable for your audience.
Course thumbnail images load as broken images or show LinkedIn login page
Cause: LinkedIn Learning CDN thumbnail URLs require authentication and cannot be hotlinked from external sites.
Solution: Download course thumbnails and host them in your own storage (Supabase Storage, Vercel Blob) rather than using LinkedIn CDN URLs directly. When adding courses to your database, fetch the thumbnail, save it to your storage, and store the public URL from your storage provider.
LinkedIn Learning API returns 403 Forbidden for learning endpoints
Cause: The LinkedIn app does not have the Learning API scopes enabled, which requires an enterprise LinkedIn Learning agreement.
Solution: The LinkedIn Learning API (r_learning_classifications, r_lms_learner_history scopes) is available only to organizations with enterprise LinkedIn Learning licenses. Contact your LinkedIn account manager to enable API access. If you don't have an enterprise license, use the database-backed catalog approach instead of direct API integration.
LinkedIn Learning iframe is blocked by browser Content Security Policy
Cause: Next.js or hosting security headers restrict which domains can be loaded in iframes, blocking LinkedIn Learning.
Solution: Add frame-src https://www.linkedin.com to your Content-Security-Policy headers in next.config.ts. Without this, modern browsers block cross-origin iframes from domains not in the allowlist.
1// next.config.ts2const nextConfig = {3 async headers() {4 return [5 {6 source: '/(.*)',7 headers: [8 {9 key: 'Content-Security-Policy',10 value: "frame-src 'self' https://www.linkedin.com;",11 },12 ],13 },14 ];15 },16};17export default nextConfig;Best practices
- Store course metadata in your own database rather than relying on LinkedIn's URLs — this protects against LinkedIn URL changes breaking your portal and lets you add custom categorization
- Download and self-host course thumbnail images to avoid broken images caused by LinkedIn CDN authentication requirements
- Add Content-Security-Policy headers explicitly allowing frame-src from linkedin.com to prevent iframe blocking by default security policies
- Use the upsert pattern for completion records to prevent duplicate entries when users re-mark courses as complete
- Display a fallback link to LinkedIn Learning alongside iframe embeds so users can access the course even if the embed fails due to subscription or browser restrictions
- For enterprise deployments, implement per-user OAuth2 to track individual completion data rather than using a single shared service account
- Cache your course catalog API response — course data changes infrequently and caching for 10-30 minutes reduces database load on high-traffic portals
Alternatives
Choose Coursera over LinkedIn Learning if your team needs university-accredited courses or degrees — Coursera partners with top universities and offers formal credentials that LinkedIn Learning does not.
Use Skillshare instead of LinkedIn Learning for creative and design-focused training — Skillshare's catalog is stronger for design, illustration, and creative business skills with a more affordable subscription.
Consider Udacity instead for intensive technical nanodegree programs in AI, data science, and cloud — Udacity offers structured programs with mentor support that LinkedIn Learning's self-paced format does not provide.
Frequently asked questions
Does LinkedIn Learning have a public API for browsing courses?
No — LinkedIn Learning does not offer a public API for searching or browsing the course catalog without an enterprise license. The Learning API is available exclusively to enterprise customers with a LinkedIn Learning organizational subscription. For non-enterprise use, the practical approach is to curate courses manually and store their metadata in your own database, then display them through your V0-generated interface.
Can I embed any LinkedIn Learning course without a subscription?
LinkedIn Learning iframes require the viewer to have an active LinkedIn Learning subscription to watch content. The embed player will show a sign-in prompt to users without a valid subscription. For public-facing pages, linking to LinkedIn Learning courses rather than embedding them is more reliable since users are directed to LinkedIn where they can subscribe or sign in.
What is the difference between Lynda.com and LinkedIn Learning?
Lynda.com was acquired by LinkedIn in 2015 and was fully rebranded to LinkedIn Learning in 2019. The Lynda.com domain now redirects to LinkedIn Learning. The content library, courses, and instructors from Lynda.com are now part of the LinkedIn Learning catalog. If you see references to 'Lynda' in older integrations or URLs, they refer to the same platform now operating as LinkedIn Learning.
How do I get course embed codes from LinkedIn Learning?
Navigate to any course on LinkedIn Learning while signed in, click the Share button (usually represented by an arrow icon near the course title), then select the Embed tab. This shows an iframe HTML snippet with the course's embed URL. Copy this entire snippet or just the src URL from the iframe tag for use in your V0 component. The embed URL format is typically https://www.linkedin.com/learning/embed/{course-slug}.
Can I track whether my team members have completed LinkedIn Learning courses?
With an enterprise LinkedIn Learning license and API access, yes — the Learning API provides learner activity reports with completion status, time spent, and assessment scores per user. Without enterprise API access, you can track completion manually by adding a 'Mark as Complete' button in your portal that stores the completion record in your own database, as shown in this guide. This self-reported completion approach works for most team learning use cases.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation