FutureLearn has no public API, so direct data integration is not possible. Instead, build your own learning platform in Bolt.new using Supabase (course catalog, video hosting, progress tracking, certificates), link out to FutureLearn courses via their affiliate program, or use Coursera's catalog API for programmatic access to online education content.
Building a Learning Platform with Bolt.new Instead of a FutureLearn API
FutureLearn is one of the UK's most prominent online learning platforms, partnering with over 250 universities and institutions globally to offer short courses, microcredentials, and full degrees. Its learner base skews toward professional upskilling in the UK and Europe. However, unlike some of its competitors, FutureLearn does not offer a public REST API that third-party developers can use to access course data, enrollment information, or learner progress.
For Bolt.new developers, this means there is no way to directly query FutureLearn course listings, check enrollment status, or sync learner progress into a custom app. The platform is designed as a destination, not as a headless service. If you came here hoping to pull FutureLearn course data into your Bolt app, the honest answer is: that is not possible with FutureLearn's current product. However, there are two genuinely useful paths available.
The first path is FutureLearn's affiliate program, which lets you link to FutureLearn courses from your Bolt-built website or app and earn commission when users enroll. This is the right choice if you are building a course recommendation website or learning resource aggregator — you curate content, link outbound to FutureLearn, and the actual learning happens on FutureLearn's platform. The second and more powerful path is building your own learning platform in Bolt.new from scratch, using Supabase as the backend for course catalogs, student accounts, video hosting, progress tracking, and certificate generation. This approach gives you full control over the experience and data. If you need programmatic access to an established course catalog, Coursera's catalog API and Teachable's REST API are the best alternatives — both are documented and accessible through Bolt's server-side API route pattern.
Integration method
FutureLearn does not provide a public API for third-party developers, so there is no direct data integration path. The two practical options are: (1) link to FutureLearn courses using their affiliate program with outbound links, or (2) build a complete learning platform in Bolt.new with Supabase that mirrors FutureLearn's functionality. For developers who need programmatic access to online course catalogs, Coursera and Teachable both offer documented REST APIs that work well through Bolt's API route pattern.
Prerequisites
- A Bolt.new account and a project using Next.js or Vite with React and TypeScript
- A Supabase account (free tier is sufficient) if building a custom learning platform
- A FutureLearn account and approval in their affiliate program (futurelearn.com/partnerships/affiliates) if building an affiliate-based portal
- A Coursera developer account at coursera.org/about/developer if using Coursera's catalog API as the FutureLearn alternative
- A deployed URL on Netlify or Bolt Cloud for any OAuth callback flows — OAuth redirects cannot complete in Bolt's WebContainer preview
Step-by-step guide
Understand FutureLearn's API limitations and choose your approach
Understand FutureLearn's API limitations and choose your approach
Before writing any code, it is important to understand why direct FutureLearn integration is not possible and which alternative best fits your project goals. FutureLearn, owned by the SEEK Group since 2022, operates as a closed learning platform. Unlike Coursera (which has a public catalog API at api.coursera.org), Udemy (which has an affiliate API), or Teachable (which has a REST API for course creators), FutureLearn has made a deliberate product decision not to expose their course data, enrollment information, or learner progress to third-party developers. There is no FutureLearn developer portal, no OAuth application registration, and no documented REST endpoints. This means any Bolt.new integration strategy must choose one of three paths: (1) The affiliate link path is best if your goal is course discovery and recommendation — you build the front end, FutureLearn delivers the learning, and you earn commission. Affiliate links are simple outbound URLs with a tracking parameter appended. No API, no backend complexity, no deployment requirements — this path works in the Bolt WebContainer preview immediately. (2) The custom platform path is best if you want to own the learning experience end-to-end. You build courses, video players, progress tracking, and certificates inside your Bolt app using Supabase as the backend. This requires more development effort but gives you complete control over content, data, and monetization. (3) The Coursera API alternative is best if you need programmatic access to an established, large-scale course catalog without building your own. Coursera provides a free public API for course discovery that returns titles, descriptions, partner names, and photos. For most Bolt.new developers building educational apps, the custom platform path with Supabase delivers the most value — you get a real product with your own brand and data, rather than sending users away to FutureLearn. Ask yourself: do you want to own the learner relationship, or refer learners to FutureLearn and earn affiliate commission? Your answer determines which path to take.
I want to build a learning platform similar to FutureLearn. Before we start coding, set up the Supabase schema. Create a SQL migration that creates these tables: (1) courses: id uuid primary key, title text, slug text unique, description text, category text, level text (Beginner/Intermediate/Advanced), duration_weeks integer, thumbnail_url text, published boolean default false, created_at timestamptz default now(). (2) lessons: id uuid primary key, course_id uuid references courses(id), title text, video_url text, duration_minutes integer, order_index integer, created_at timestamptz default now(). (3) enrollments: id uuid primary key, user_id uuid references auth.users(id), course_id uuid references courses(id), enrolled_at timestamptz default now(), unique(user_id, course_id). (4) lesson_completions: id uuid primary key, user_id uuid references auth.users(id), lesson_id uuid references lessons(id), completed_at timestamptz default now(), unique(user_id, lesson_id). Add RLS policies so users can only read their own enrollments and completions.
Paste this in Bolt.new chat
1-- supabase/migrations/001_learning_platform.sql2-- Course catalog3CREATE TABLE courses (4 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),5 title TEXT NOT NULL,6 slug TEXT UNIQUE NOT NULL,7 description TEXT,8 category TEXT,9 level TEXT CHECK (level IN ('Beginner', 'Intermediate', 'Advanced')),10 duration_weeks INTEGER,11 thumbnail_url TEXT,12 published BOOLEAN DEFAULT false,13 created_at TIMESTAMPTZ DEFAULT now()14);1516-- Lessons within courses17CREATE TABLE lessons (18 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),19 course_id UUID REFERENCES courses(id) ON DELETE CASCADE,20 title TEXT NOT NULL,21 video_url TEXT,22 duration_minutes INTEGER,23 order_index INTEGER NOT NULL,24 created_at TIMESTAMPTZ DEFAULT now()25);2627-- User enrollments28CREATE TABLE enrollments (29 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),30 user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,31 course_id UUID REFERENCES courses(id) ON DELETE CASCADE,32 enrolled_at TIMESTAMPTZ DEFAULT now(),33 UNIQUE(user_id, course_id)34);3536-- Lesson completion tracking37CREATE TABLE lesson_completions (38 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),39 user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,40 lesson_id UUID REFERENCES lessons(id) ON DELETE CASCADE,41 completed_at TIMESTAMPTZ DEFAULT now(),42 UNIQUE(user_id, lesson_id)43);4445-- RLS policies46ALTER TABLE courses ENABLE ROW LEVEL SECURITY;47ALTER TABLE lessons ENABLE ROW LEVEL SECURITY;48ALTER TABLE enrollments ENABLE ROW LEVEL SECURITY;49ALTER TABLE lesson_completions ENABLE ROW LEVEL SECURITY;5051-- Anyone can read published courses and their lessons52CREATE POLICY "Public read published courses" ON courses FOR SELECT USING (published = true);53CREATE POLICY "Public read lessons" ON lessons FOR SELECT USING (true);5455-- Users manage their own enrollments and completions56CREATE POLICY "Users manage own enrollments" ON enrollments57 USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid());58CREATE POLICY "Users manage own completions" ON lesson_completions59 USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid());Pro tip: If you choose the affiliate path instead of building a custom platform, you do not need any Supabase setup. Simply store course metadata (title, description, FutureLearn affiliate URL) in a static JSON file or a simple Supabase table — the 'integration' is purely outbound links.
Expected result: The Supabase database has four tables with proper relationships and RLS policies. The schema is ready for building course catalog, lesson player, and progress tracking features in subsequent steps.
Build the course catalog page with enrollment
Build the course catalog page with enrollment
With the database schema in place, the next step is building the course discovery and enrollment flow. The catalog page shows all published courses with their titles, categories, difficulty levels, duration, and thumbnails. For authenticated users, it shows whether they are already enrolled in each course. The enrollment action inserts a row into the enrollments table and redirects the user to the first lesson. The catalog page is a React Server Component that queries Supabase for published courses. For the enrollment check, you fetch the current user's enrollments and compare them against the course list client-side. This avoids N+1 queries — one query for courses, one query for the user's enrollments, then a JavaScript join. For course thumbnails, Supabase Storage is the recommended approach: upload images to a public bucket called 'course-thumbnails' and store the public URL in the courses table. Alternatively, use external image URLs (from Unsplash or your own CDN) stored directly in the thumbnail_url column. The learning platform does not need native FutureLearn thumbnails since you are building your own content. The category filter uses client-side state to filter the visible course cards without re-fetching from the server. This works well for catalogs up to a few hundred courses. For larger catalogs, move filtering to the Supabase query with a WHERE clause on the category column. The difficulty level filter works the same way. When a user clicks 'Enroll', the component calls a Server Action that inserts into the enrollments table. Server Actions are the correct pattern for database mutations in Next.js App Router — they run on the server, have access to process.env credentials, and do not require a separate API route. After enrollment, the user is redirected to the first lesson in the course.
Build a course catalog page at app/courses/page.tsx. It should: (1) Fetch all published courses from Supabase (title, slug, description, category, level, duration_weeks, thumbnail_url), (2) Show courses as grid cards with thumbnail, title, category badge, level badge, and duration, (3) Add filter buttons at the top for categories (All, Technology, Business, Health, Creative), (4) Add a 'Enroll Now' button on each card that calls a server action to insert into the enrollments table for the logged-in user, (5) Show 'Continue Learning' instead of 'Enroll Now' for already-enrolled courses, (6) Use Tailwind CSS and shadcn/ui Card components. Fetch the current user's enrollments to determine enrollment state.
Paste this in Bolt.new chat
1// app/courses/actions.ts2'use server';3import { createClient } from '@/lib/supabase/server';4import { redirect } from 'next/navigation';56export async function enrollInCourse(courseId: string, firstLessonId?: string) {7 const supabase = await createClient();8 const { data: { user } } = await supabase.auth.getUser();910 if (!user) {11 redirect('/login');12 }1314 const { error } = await supabase15 .from('enrollments')16 .insert({ user_id: user.id, course_id: courseId });1718 if (error && error.code !== '23505') {19 // 23505 = unique constraint violation (already enrolled)20 throw new Error(`Enrollment failed: ${error.message}`);21 }2223 if (firstLessonId) {24 redirect(`/lessons/${firstLessonId}`);25 }26}Pro tip: Seed your Supabase courses table with 4-6 example courses so the catalog page has content to display immediately in the Bolt preview. Use Supabase's Table Editor to insert rows directly, or add a seed SQL file to your migrations folder.
Expected result: The course catalog page shows published courses as styled cards with category filters. Clicking 'Enroll Now' inserts an enrollment record and the button changes to 'Continue Learning' for enrolled courses.
Build the lesson player with progress tracking
Build the lesson player with progress tracking
The lesson player is the core of the learning experience. Each lesson page shows the video embed, the lesson title, the course navigation sidebar (all lessons in the course with completion indicators), and a 'Mark as Complete' button. When the user clicks 'Mark as Complete', a Server Action inserts a row into the lesson_completions table and updates the sidebar state. For video embedding, YouTube is the simplest and most reliable approach for a Bolt-built learning platform: store the YouTube video URL or ID in the video_url column and embed it using a standard iframe. The YouTube embed URL format is https://www.youtube.com/embed/{videoId}. For private or custom video content, use Supabase Storage with a signed URL. Supabase Storage supports direct video streaming and generates time-limited signed URLs for private content — prompt Bolt to generate an API route that creates a signed URL from SUPABASE_SERVICE_ROLE_KEY. The progress sidebar shows all lessons in the course with a checkmark icon for completed lessons. This sidebar is a Client Component that receives the initial completion state as a prop from the Server Component parent, and updates optimistically when the user marks a lesson complete. Optimistic UI means the checkbox appears checked immediately when clicked, before the database write confirms — this makes the interface feel instant even on slow connections. Course completion is calculated as (completed lessons / total lessons) * 100. Display this as a progress bar at the top of the sidebar. When the percentage reaches 100%, show a congratulations message and a link to download or view the course certificate. The certificate feature is covered in the next step. Navigation between lessons uses the order_index column. The 'Next Lesson' button fetches the lesson with order_index + 1 in the same course. The 'Previous Lesson' button uses order_index - 1. Handle edge cases: no previous lesson on the first lesson, no next lesson on the last lesson.
Build a lesson player page at app/lessons/[lessonId]/page.tsx. It should: (1) Fetch the lesson and its parent course from Supabase using the lessonId param, (2) Embed the lesson video as a YouTube iframe (extract video ID from the video_url), (3) Show a sidebar with all lessons in the course, sorted by order_index, with a checkmark for completed lessons, (4) Show a progress bar at the top of the sidebar showing completion percentage, (5) Show a 'Mark as Complete' button that calls a server action to insert into lesson_completions, (6) Show 'Next Lesson' and 'Previous Lesson' navigation buttons, (7) Handle the case where the user is not enrolled in the course by redirecting them to the course catalog page.
Paste this in Bolt.new chat
1// app/lessons/[lessonId]/actions.ts2'use server';3import { createClient } from '@/lib/supabase/server';4import { revalidatePath } from 'next/cache';56export async function markLessonComplete(lessonId: string, courseSlug: string) {7 const supabase = await createClient();8 const { data: { user } } = await supabase.auth.getUser();910 if (!user) return { error: 'Not authenticated' };1112 const { error } = await supabase13 .from('lesson_completions')14 .insert({ user_id: user.id, lesson_id: lessonId });1516 if (error && error.code !== '23505') {17 return { error: error.message };18 }1920 revalidatePath(`/lessons/${lessonId}`);21 return { success: true };22}2324export async function getProgressForCourse(courseId: string, userId: string) {25 const supabase = await createClient();2627 // Get total lesson count28 const { count: total } = await supabase29 .from('lessons')30 .select('*', { count: 'exact', head: true })31 .eq('course_id', courseId);3233 // Get completed count for this user34 const { data: completions } = await supabase35 .from('lesson_completions')36 .select('lesson_id, lessons!inner(course_id)')37 .eq('user_id', userId)38 .eq('lessons.course_id', courseId);3940 const completed = completions?.length ?? 0;41 const percentage = total ? Math.round((completed / total) * 100) : 0;4243 return { completed, total: total ?? 0, percentage };44}Pro tip: Use YouTube's privacy-enhanced embed URL (https://www.youtube-nocookie.com/embed/{videoId}) instead of the standard embed URL. The privacy-enhanced mode does not track viewers with YouTube cookies until they click play — a better experience for your learners.
Expected result: The lesson player shows the video embed, a sidebar with all course lessons and completion checkmarks, a progress bar, and a 'Mark as Complete' button. Clicking the button updates the checkmark in the sidebar instantly.
Set up the FutureLearn affiliate link path as an alternative
Set up the FutureLearn affiliate link path as an alternative
If building a full custom learning platform is more than your project requires, the FutureLearn affiliate program is a much simpler integration path. FutureLearn's affiliate program lets you link to their courses with a tracking parameter appended to the URL. When a user clicks your link and enrolls in a FutureLearn course within the attribution window, you earn a commission (typically 10-30% of the course fee). This approach is essentially outbound linking with revenue sharing — no API, no backend, no deployment required. To join the FutureLearn affiliate program, go to futurelearn.com/partnerships/affiliates and apply. FutureLearn uses an affiliate network (historically Impact or Awin) — after approval, you get access to a dashboard where you can generate affiliate links, create banners, and track your earnings. The affiliate link format is typically: https://www.futurelearn.com/courses/{course-slug}?utm_source={your_affiliate_id}&utm_medium=affiliate. For a Bolt-built course recommendation portal, store your curated course list in a Supabase table with columns for title, provider, description, image URL, affiliate URL, and metadata. The portal fetches this table and renders course cards. The 'View Course' or 'Enroll' button on each card opens the affiliate URL in a new tab. This is a pure content site — no authentication, no server-side API calls, no environment variables needed. It works completely in the Bolt WebContainer preview. Note a key limitation: since FutureLearn has no API, your course database must be maintained manually. You cannot automatically sync new courses, price changes, or availability. For a small curated catalog (20-50 courses), this is manageable. For a large-scale course aggregator, a platform with a real API (like Coursera or Udemy) is a better fit. For Bolt's WebContainer context: this affiliate approach generates zero WebContainer-related issues. There are no incoming webhooks, no API rate limits, no native modules, no CORS concerns. Outbound links work exactly the same in Bolt's preview as in production.
Create a Supabase table called 'affiliate_courses' with columns: id uuid primary key default gen_random_uuid(), title text not null, provider text default 'FutureLearn', category text, level text, duration_weeks integer, description text, image_url text, affiliate_url text not null, featured boolean default false, created_at timestamptz default now(). Enable row level security with a policy allowing public read access (no authentication required). Then build a React page at app/recommended-courses/page.tsx that fetches all rows from this table and displays them as course cards with an affiliate link button. Add Tailwind CSS styling and a category filter. Seed the table with 4 example FutureLearn course entries.
Paste this in Bolt.new chat
1// Example affiliate course data for seeding2// Insert via Supabase Table Editor or SQL:3/*4INSERT INTO affiliate_courses (title, provider, category, level, duration_weeks, description, image_url, affiliate_url, featured)5VALUES6 (7 'Introduction to Data Science',8 'FutureLearn',9 'Technology',10 'Beginner',11 4,12 'Learn data science fundamentals with Python, covering data analysis, visualization, and machine learning basics.',13 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=400',14 'https://www.futurelearn.com/courses/data-science',15 true16 ),17 (18 'Digital Marketing Strategy',19 'FutureLearn',20 'Business',21 'Intermediate',22 6,23 'Master digital marketing channels including SEO, social media, email marketing, and paid advertising.',24 'https://images.unsplash.com/photo-1432888622747-4eb9a8efeb07?w=400',25 'https://www.futurelearn.com/courses/digital-marketing',26 true27 );28*/2930// app/recommended-courses/page.tsx31import { createClient } from '@/lib/supabase/server';3233export default async function RecommendedCoursesPage() {34 const supabase = await createClient();35 const { data: courses } = await supabase36 .from('affiliate_courses')37 .select('*')38 .order('featured', { ascending: false })39 .order('created_at', { ascending: false });4041 return (42 <div className="mx-auto max-w-6xl px-4 py-12">43 <h1 className="mb-2 text-3xl font-bold">Recommended Courses</h1>44 <p className="mb-8 text-gray-600">Curated courses from FutureLearn and partner institutions</p>45 <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">46 {courses?.map((course) => (47 <div key={course.id} className="rounded-xl border bg-white p-0 shadow-sm overflow-hidden">48 {course.image_url && (49 <img src={course.image_url} alt={course.title} className="h-48 w-full object-cover" />50 )}51 <div className="p-5">52 <span className="text-xs font-medium uppercase text-blue-600">{course.category}</span>53 <h2 className="mt-1 text-lg font-semibold">{course.title}</h2>54 <p className="mt-2 text-sm text-gray-600 line-clamp-2">{course.description}</p>55 <div className="mt-3 flex items-center gap-3 text-xs text-gray-500">56 <span>{course.level}</span>57 <span>·</span>58 <span>{course.duration_weeks} weeks</span>59 </div>60 <a61 href={course.affiliate_url}62 target="_blank"63 rel="noopener noreferrer"64 className="mt-4 block w-full rounded-lg bg-blue-600 py-2 text-center text-sm font-medium text-white hover:bg-blue-700"65 >66 View on FutureLearn67 </a>68 </div>69 </div>70 ))}71 </div>72 </div>73 );74}Pro tip: FutureLearn courses can be browsed at futurelearn.com/courses — use the filter options to find courses by subject, level, and duration. Copy the course URL, sign up for the affiliate program to get your tracking parameter, and append it to each course URL you store in your database.
Expected result: The recommended courses page shows a grid of FutureLearn course cards fetched from Supabase. Each card has a 'View on FutureLearn' button that opens the affiliate URL in a new tab. The entire page works in Bolt's WebContainer preview with no API credentials needed.
Use Coursera's API as the programmatic alternative to FutureLearn
Use Coursera's API as the programmatic alternative to FutureLearn
For developers who specifically need programmatic access to a large course catalog — the kind of integration you would use FutureLearn for if they had an API — Coursera is the most practical alternative. Coursera provides a public REST API at api.coursera.org that returns course listings, partner information, and course metadata. The API is free to use for catalog data and requires no OAuth for basic course discovery queries. Coursera's catalog API follows a standard REST pattern. The courses endpoint is GET https://api.coursera.org/api/courses.v1 and accepts query parameters including q (query type: search or browse), query (search terms), fields (comma-separated list of fields to return), and limit/start for pagination. Fields available include name, slug, photoUrl, description, and partnerIds. This API is HTTP-based and works perfectly through a Bolt.new Next.js API route — outbound calls from the server side have no CORS issues. The API route pattern is straightforward: your React component calls your own /api/courses endpoint, which adds any required headers and calls api.coursera.org, then returns the cleaned data to the frontend. This proxy pattern serves two purposes: it keeps any API credentials server-side (though Coursera's catalog API does not require credentials for basic queries), and it lets you add caching, error handling, and response transformation in one place. Pagination is important for a good user experience. Coursera's API returns results with a paging object containing a next cursor. Implement infinite scroll or 'Load More' pagination in the React component using the cursor from the previous response. Store the cursor in component state and include it as a start parameter in the next API call. Note that Coursera's API is designed for course discovery, not for managing enrollments or accessing learner data — those features require Coursera's enterprise integration (Coursera for Campus or Coursera for Business). For a Bolt.new app building a learning resource aggregator, the catalog API is exactly the right level of access.
Build a Coursera course discovery feature. Create a Next.js API route at app/api/coursera/search/route.ts that accepts a GET request with a 'query' search param, calls https://api.coursera.org/api/courses.v1?q=search&query={query}&fields=name,slug,photoUrl,description,partnerIds&limit=12, and returns the results. Then build a React page at app/discover/page.tsx with a search input and a grid of Coursera course cards. Each card shows the course photo, name, and description. Add a 'View Course' button linking to https://www.coursera.org/learn/{slug}. Show a loading spinner while searching. Handle empty results and API errors gracefully.
Paste this in Bolt.new chat
1// app/api/coursera/search/route.ts2import { NextRequest, NextResponse } from 'next/server';34interface CourseraCoursesResponse {5 elements: Array<{6 id: string;7 name: string;8 slug: string;9 photoUrl?: string;10 description?: string;11 partnerIds?: string[];12 }>;13 paging?: { next?: string };14}1516export async function GET(request: NextRequest) {17 const { searchParams } = new URL(request.url);18 const query = searchParams.get('query') ?? 'programming';19 const start = searchParams.get('start') ?? '0';2021 try {22 const url = new URL('https://api.coursera.org/api/courses.v1');23 url.searchParams.set('q', 'search');24 url.searchParams.set('query', query);25 url.searchParams.set('fields', 'name,slug,photoUrl,description,partnerIds');26 url.searchParams.set('limit', '12');27 url.searchParams.set('start', start);2829 const response = await fetch(url.toString(), {30 headers: {31 'Accept': 'application/json',32 },33 next: { revalidate: 300 }, // Cache for 5 minutes34 });3536 if (!response.ok) {37 return NextResponse.json(38 { error: `Coursera API error: ${response.status}` },39 { status: response.status }40 );41 }4243 const data: CourseraCoursesResponse = await response.json();4445 return NextResponse.json({46 courses: data.elements.map((course) => ({47 id: course.id,48 name: course.name,49 slug: course.slug,50 photoUrl: course.photoUrl,51 description: course.description,52 courseUrl: `https://www.coursera.org/learn/${course.slug}`,53 })),54 nextCursor: data.paging?.next,55 });56 } catch (error) {57 const message = error instanceof Error ? error.message : 'Request failed';58 return NextResponse.json({ error: message }, { status: 500 });59 }60}Pro tip: Coursera's public catalog API has rate limits. Add next: { revalidate: 300 } to your fetch call (as shown in the code) to cache API responses for 5 minutes in Next.js. This reduces repeat API calls when multiple users search for the same query.
Expected result: The Coursera course discovery page shows a search input and a grid of course results fetched from Coursera's API. Typing a search query like 'machine learning' or 'web development' returns relevant courses from Coursera's catalog.
Common use cases
Course Recommendation Portal with FutureLearn Affiliate Links
A content website that curates online learning resources for a specific niche (e.g., data science, healthcare, sustainability) and links to relevant FutureLearn courses using affiliate URLs. The portal is built in Bolt.new with a Supabase database of manually curated course metadata, and earns commission when users click through and enroll on FutureLearn.
Build a course recommendation portal for data science learners. Create a Supabase table called 'courses' with columns: id, title, provider, url, affiliate_url, category, duration_weeks, difficulty, description, image_url, rating. Seed it with 6 example FutureLearn courses. Build a Next.js page that displays courses as cards with title, provider badge, duration, difficulty badge, and a 'View Course' button that opens the affiliate_url. Add filter buttons for category and difficulty. Use Tailwind CSS and shadcn/ui components.
Copy this prompt to try it in Bolt.new
Custom Learning Platform with Supabase Backend
A full learning management system built in Bolt.new using Supabase: course catalog, video lessons via Supabase Storage or YouTube embeds, lesson completion tracking per user, quiz results, and downloadable certificates. This replicates FutureLearn-style functionality entirely within your own product, with full control over content and data.
Build a learning platform with Supabase. Create these tables: courses (id, title, description, thumbnail_url, category, level), lessons (id, course_id, title, video_url, duration_minutes, order_index), user_progress (id, user_id, lesson_id, completed_at), enrollments (id, user_id, course_id, enrolled_at). Build a course catalog page showing enrolled and available courses. Build a lesson player page with a YouTube embed, a 'Mark Complete' button that inserts into user_progress, and a progress bar showing completion percentage. Use Supabase Auth for user sessions. Use Tailwind CSS.
Copy this prompt to try it in Bolt.new
Tech Education Dashboard Using Coursera API
For developers who need programmatic access to an online course catalog, Coursera's catalog API provides public access to course listings, descriptions, and partner information. This Bolt.new app fetches course data from Coursera's API and displays it in a searchable dashboard — achieves what a FutureLearn API would provide, using Coursera's documented endpoints.
Build a course discovery dashboard that fetches programming courses from Coursera's API. Create a Next.js API route at /api/courses that calls https://api.coursera.org/api/courses.v1?q=search&query=javascript&fields=name,slug,photoUrl,description,partnerIds and returns the results. In the frontend, show a search input and display results as cards with course name, photo, and a link to the Coursera course page. Add a loading skeleton. Handle API errors with a user-friendly message. Use Tailwind CSS.
Copy this prompt to try it in Bolt.new
Troubleshooting
Supabase query returns empty array even though courses were inserted in the Table Editor
Cause: The courses table has a published column with a default of false, and the query filters for WHERE published = true. Newly inserted courses have published = false unless explicitly set.
Solution: In Supabase Table Editor, edit the course rows you inserted and set published = true. Alternatively, update your Supabase query during development to remove the published filter: .select('*') without .eq('published', true). Add the filter back when you are ready for production.
1// Development: no filter2const { data: courses } = await supabase.from('courses').select('*');34// Production: only show published courses5const { data: courses } = await supabase6 .from('courses')7 .select('*')8 .eq('published', true);Coursera API returns a 404 or the fetch call fails with a CORS error in the browser console
Cause: The Coursera API call is being made from the client-side React component directly, not through the Next.js API route. Direct browser-to-Coursera API calls may fail due to CORS restrictions. Alternatively, the API route path may be incorrect.
Solution: Ensure the Coursera API call happens inside the Next.js API route at app/api/coursera/search/route.ts, not in the React component. The React component should call /api/coursera/search?query=javascript, which then proxies to Coursera. Never call api.coursera.org directly from browser-side React code.
1// WRONG: Direct call from React component2const data = await fetch('https://api.coursera.org/api/courses.v1?...');34// CORRECT: Call your own API route proxy5const data = await fetch(`/api/coursera/search?query=${encodeURIComponent(searchQuery)}`);The YouTube video embed shows 'Video unavailable' or a blank iframe in the lesson player
Cause: The video_url stored in Supabase is either the full watch URL (https://www.youtube.com/watch?v=VIDEO_ID) rather than the embed URL, the video ID is missing, or the video has embedding disabled by the YouTube channel owner.
Solution: Extract the video ID from the full YouTube URL and construct the embed URL. The embed format is https://www.youtube.com/embed/{videoId}. Parse the video ID from watch URLs (v= parameter) or short URLs (youtu.be/{id}). Test with a video you control or know has embedding enabled — not all YouTube videos allow embedding on external sites.
1// Extract YouTube video ID from any YouTube URL format2function getYouTubeEmbedUrl(url: string): string {3 const patterns = [4 /youtube\.com\/watch\?v=([^&]+)/,5 /youtu\.be\/([^?]+)/,6 /youtube\.com\/embed\/([^?]+)/,7 ];8 for (const pattern of patterns) {9 const match = url.match(pattern);10 if (match) return `https://www.youtube-nocookie.com/embed/${match[1]}`;11 }12 return url; // Return as-is if already an embed URL13}The affiliate link tracking is not working — FutureLearn's affiliate dashboard shows zero clicks
Cause: The affiliate tracking parameter is missing from the course URL, the affiliate network tracking parameter format has changed, or users are using browser extensions that strip tracking parameters from URLs.
Solution: Verify your affiliate link format by clicking it yourself and checking that the affiliate network registers the click in their dashboard. Affiliate network link formats vary: Impact uses impact.com tracking links, Awin uses aw.ncsbn.com redirects. Use the link builder in your affiliate network's dashboard rather than manually appending parameters. Some ad blockers strip tracking parameters — test in an incognito browser without extensions.
Best practices
- Be transparent with your users: if you are building a course recommendation portal with affiliate links, make it clear that you may earn a commission when they enroll — this builds trust and is required by FTC guidelines
- Store your curated course metadata in Supabase rather than hardcoding it in React — this allows you to add, edit, or remove courses without redeploying your Bolt app
- For the custom learning platform path, always enable Row Level Security on all Supabase tables and write explicit policies — without RLS, all course data and user progress is publicly accessible
- Use Supabase Storage for course videos only if your content is private or proprietary — for public educational content, YouTube embeds are free, globally cached, and more reliable than self-hosted video
- Cache Coursera API responses in your Next.js API route using the fetch next: { revalidate: N } option — repeated identical searches will return cached results without hitting Coursera's rate limits
- Keep the lesson_completions and enrollments tables indexed on (user_id, course_id) for fast progress queries — as your platform grows, unindexed queries on these tables will slow down
- For the affiliate path, manually review and update your course list quarterly — FutureLearn courses change prices, go on hiatus, or get retired, and dead links hurt user experience and SEO
Alternatives
Choose Coursera if you need a public REST API to programmatically fetch course listings, partner information, and metadata — Coursera has documented developer endpoints that FutureLearn does not provide.
Choose Teachable if you want to sell your own courses with an API for managing students, enrollments, and course content — Teachable has a REST API for course creators that integrates well with Bolt.new.
Consider Udacity for tech career-focused nanodegree content, though like FutureLearn they have no public API — both platforms require the affiliate or custom-build approach.
Choose Skillshare if your audience is focused on creative and design skills, and you want to recommend courses via their affiliate program in a similar pattern to FutureLearn.
Frequently asked questions
Does FutureLearn have a public API that works with Bolt.new?
No. FutureLearn does not offer a public REST API for third-party developers. There is no developer portal, no OAuth application registration, and no documented endpoints for accessing course data, enrollment status, or learner progress. If you need programmatic access to online course data, Coursera's catalog API is the closest alternative that works with Bolt.new's API route pattern.
How do I add FutureLearn course links to my Bolt.new app?
Join FutureLearn's affiliate program at futurelearn.com/partnerships/affiliates to get tracking links for each course. Store the course metadata (title, description, image, affiliate URL) in a Supabase table and build a course recommendation page in Bolt that links out to FutureLearn. The entire implementation is outbound links — no API key, no backend API calls, and it works in Bolt's WebContainer preview immediately.
Can I build something similar to FutureLearn inside Bolt.new?
Yes — Bolt.new with Supabase is well-suited for building a custom learning platform. Supabase provides the database for course catalogs, user accounts, and progress tracking. For video hosting, use YouTube embeds (free) or Supabase Storage (for private content). Certificate generation can be done with a PDF library like pdf-lib or jsPDF. The schema in this guide covers the core data model for courses, lessons, enrollments, and progress tracking.
Which online learning platform has the best API for use with Bolt.new?
Coursera has the most accessible public API for course discovery — free to use, no authentication required for catalog queries, and HTTP-based so it works through Bolt's Next.js API route pattern. Teachable and Thinkific have REST APIs for course creators who want to manage their own course content programmatically. Udemy has an affiliate API. FutureLearn, Udacity, and LinkedIn Learning (Lynda) do not have public APIs available for independent developers.
Does building a custom learning platform in Bolt.new require deployment to work?
The course catalog, lesson player, and progress tracking features work in Bolt's WebContainer preview since they use Supabase (HTTP-based) for the backend. Authentication with Supabase Auth also works in preview for email/password flows. The main features that require deployment are OAuth social login (Google, GitHub) — these need a stable redirect URI that the WebContainer's dynamic URL cannot provide. Deploy to Netlify or Bolt Cloud to enable social login.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation