It’s never been easier to learn new professional skills online. As the demand for online learning resources continually increases, educational marketplaces have become more ubiquitous than ever. With platforms like LinkedIn Learning, formerly Lynda, creators can easily package and share their knowledge to a network of like-minded individuals. If you were interested in building your own education platform, you’d traditionally need first-hand experience as a software developer or access to a team of engineers. But with Bubble’s visual programming tool, makers across the world can build their own marketplaces, social networks, mobile apps, and more—all without writing a single line of code.
Throughout this post, we’ll break down the process of using Bubble to build your version of LinkedIn Learning. This guide will share how to start building the underlying workflows for your MVP.
The steps to building a LinkedIn Learning clone with no code include:
Before you start, you’ll need to first register your free Bubble account. Click the button below to get started, then you can follow along as we build our product together.
Register your account on Bubble.
We also recommend completing our introductory lessons, which will guide you through the step-by-step process of the most common Bubble features. This will help you get a running start when building your LinkedIn Learning clone.
When starting your project, you can choose to begin by wireframing your product design: building the necessary fields within your database.
In this case, we’ll start by using Bubble’s visual design tool to shape the user interface of our platform. If you’re replicating LinkedIn Learning, some of the core pages you’ll want to include are:
- Course creation page: A backend portal for creators to upload new courses
- Home page: Including a search bar for users to discover relevant courses
- Course page: A dedicated page to host the content of each unique course
A major feature within Bubble is the ability to send data between pages. This allows you to create one generic version of a page, then dynamically display the relevant content from your database when it’s required.
In the case of your LinkedIn Learning clone, you’ll only need to create one page to host each individual course (we’ll cover this in more detail soon).
Configuring your database
Once you’ve mapped out the display of your product, you can focus on creating the necessary data fields to power your application. We’ll rely on these fields to connect the workflows behind your product.
Bubble’s pre-built database makes it easy to create different data types with unique fields. When creating a database, we recommend splitting larger items into separate data types to enhance the speed of your application.
For example, instead of storing all of the data for each course under one property, we’ll split this content into separate course module data types, then link them back to the same course.
By forking these as separate data types, it allows us to only load the necessary content when it’s needed, reducing the amount of data the Bubble editor will need to render.
When building our LinkedIn Learning MVP, we’ll need to create the following data types & fields:
Data type: User
Data type: Course
- Featured image
- Course modules – List of course modules.
- Published - Yes/no with “no” default
- Students – List of users
Data type: Course-module
- Module title
- Module description
- Module content
Now that you’ve structured both the design and database of your application, it’s time to start stitching everything together to make your app functional.
In Bubble, the main way to do this is with workflows. Each workflow happens when an event occurs (e.g. a user clicks on a button) and then runs a series of “actions” in response (like “sign the user up” or “make a change to the database”).
Creating a course
The first feature we’ll build is a function that allows creators to build and publish their own courses to the platform.
On the upload-course page, we’ll start by adding a variety of input elements that will allow us to add data into our database. This first page will be used to create the initial details of a course itself.
After configuring our page elements, we’ll create a trigger for our first workflow. This event will launch when the add modules button is clicked.
Within this workflow, we’ll be creating a thing: a new course.
We’ll then need to start adding the relevant fields within our database. Map each of the on-page input elements with their corresponding database field.
Now that we’ve created the framework for a course, we’ll add another event to this workflow, sending the course creator to our next page where they can add a list of modules to the course itself.
Using a navigation event, we’ll direct the user to our upload-module page, sending with them the data from the new course they just created.
When sending data to a page, it’s important to configure the content type of a landing page to match the data in which you’ll be sending through your workflow.
In this instance, we’ll need to set the upload-module page to be a course type.
After configuring the page type, we’ll once again use a combination of input fields to create a new module within our current course.
Below our module input fields, we’ll also add a repeating group element to display a list of all the modules added to this current course.
When adding this repeating group, we’ll need to first configure the type of content it will display: course modules.
Next, we’ll configure the data source, allowing it to display the relevant course modules as they’re created.
To achieve this, we’ll do a search for all of the course modules where the course equals the current page’s course.
Now you’re ready to start structuring the dynamic content that will be displayed within each grid. Simply map out the top row with the relevant content you’d like to show, then this powerful element will populate the remaining columns based on your existing data.
This repeating group will now display a list of all the modules we add to a course in chronological order.
After structuring our entire page, we’re ready to now create a workflow that adds a new module to our current page’s course.
We’ll create a workflow trigger when our add module button is clicked.
Within this workflow, we’ll be creating a new thing: a new course module. Once again, we’ll start matching our on-page elements with the relevant data fields in our database.
When matching the data fields, we’ll also link the new module to the current page's course.
Once a new module is added, it will automatically be displayed within the on-page repeating group.
In order to add multiple modules through the same inputs, we’ll also need to add an additional step to our workflow, resetting our input elements once a module has been created.
After a creator finishes adding all of their modules to the course, they can finally publish the course by clicking the publish button.
As both our course and course modules have already been created, we’ll be using this workflow to instead make changes to a thing.
The thing we’ll want to change is the current page’s course, updating its published status to “yes.”
This will now verify that the course is ready to be visible across the platform.
Display courses in a feed
Once creators begin publishing courses to the platform, we can start building a function to display these as a dynamic list on our home page.
We can easily display our courses as a list by adding another repeating group.
When using a repeating group, you’ll need to first link the element to a data type within your database. In this instance, you’ll classify the type of content as courses.
You’ll also need to set the data source as a list of all the courses from your database.
By also adding an additional constraint to our data source, it will allow us to only display courses where the published status = “yes.”
Once again, you can then map out the content that will be displayed within each repeating group cell. In this instance, it will include the course's featured image, the course's title, and the name of the course's creator.
Building a search function
Although our home page will display a list of all the available courses across our platform, we can also build an additional search function, allowing users to quickly discover relevant courses.
By using a text input field as a search bar, we can update the data source of our repeating group based on the value of this element.
Using Bubble’s conditions feature, we can modify the behavior of elements when specific criteria are met.
In this case, we’ll add a condition to our repeating group that identifies when the text search bars value is not empty.
When this condition has been met, we’ll opt to change the data source of the repeating group, this time searching for courses where the course title contains the value of the search bar.
Now, this repeating group will dynamically update each time a user searches for a course.
Sending data between pages
Within a repeating group, it’s also possible to create events inside each individual column. This feature will become useful when building navigation function across your platform.
As each cell only displays an overview of each course, we’ll want to display the full course details for each unique item on a separate page. This additional content will need to be hosted on your dedicated course page.
To power this event, you’ll need to start by creating a workflow that redirects a user to your course page when the course’s image is clicked.
Within this workflow, use a navigation event to send a user to another page. From here, select the destination page type to be the course page.
You’ll then need to send additional data to this page so the Bubble editor knows which specific course to display. The data you’ll need to display is that of the current cell's course.
Display dynamic content on a course page
Once a user has been redirected to a specific course page, you can easily pull this event data from your workflow and display the relevant content.
Once again, we’ll need to configure the page type of our destination page to match the data type that’s being sent through your workflow.
In this case, you’ll set the course page to a course property.
From here, you can then start adding dynamic content into your page elements, displaying the information from the course that has been sent in your workflow.
On this page, we’ll also add a popup element to display the video content of each course module.
When adding this element, configure the type of content it displays to be a course module.
Once we’ve added this element, we’ll need to create a workflow that causes this popup to display.
Back on our course page, we’ll add another repeating group that displays a list of all the modules added to a specific course.
Now, when the title of a course module is clicked, it will trigger our next workflow.
In this workflow, we’ll want to start by choosing to display data onto our popup element.
The data we’ll want to display is that of the current cell's course module.
We’ll also need to add a condition to this workflow that only allows it to run when a user is registered as a student for this course. As we’ll be adding a paywall to our courses, this will limit access to only the users who have paid for the content.
Once the data of a course module has been sent to our popup, we’ll need to create an additional step in our workflow to display the element itself.
Once again, we’ll also add an “only when” statement to this workflow to restrict the access to paid users.
Now, when a user clicks on a module, it will display the content, allowing them to actively watch the course.
Building a checkout
When building a feature to paywall content, we’ll need to create a checkout experience for processing payments on our platform.
Within Bubble, it’s possible to harness the power of several plugins to facilitate these necessary workflows.
In this guide, we’ll be using the Stripe.js plugin to process credit card payments through Stripe.
Once we’ve added the Stripe plugin, we can then start to build the interface for our payment solution. For our LinkedIn Learning MVP, we’ll make use of another popup element to display a payment form.
On our popup, we’ll map out a payment form where a user can add their payment details. At this point, we’ll also need to configure the type of popup to be a course.
On your popup, you’ll also need to include a Stripe token element next to the payment form. This element won’t be visible to your end-users but is essential to powering a new transaction in Stripe.
We’ll then create a new workflow that triggers a Stripe payment when the purchase button is clicked to complete this checkout process.
Throughout this workflow, start by selecting the event “convert card into Stripetoken A.” Within this event, you’ll need to configure your input fields to match Stripe's payment structure.
Once a card has been converted into a Stripe token, you’ll then need to create an additional workflow that automatically processes this token from a user's bank account.
Using the “Stripe.js - charge - create” event, you’ll verify the Stripe token, as well as the final amount to be paid (including the currency).
After a payment has been processed, we’ll then need to add one more step into our workflow: adding a user to the course's list of students. When a user is added to the list of course students, they’ll gain access to the content within a course.
If you’d like additional guidance when building your payment processing workflow, you can watch a full tutorial in the video below.
Now that we’ve built the necessary workflows to process a payment, we’ll need to head back to our course page and build a workflow that triggers our payment popup to display.
We’ll create a workflow trigger when the buy button is clicked.
Once again, we’ll start by selecting the display data event, sending the data of the current page's course to our checkout popup.
Finally, we’ll add the last step of the workflow, choosing to display the popup itself.
Sending data from our page will allow our popup to maintain the details of our course, including its title, price, and description.
After completing this workflow, our checkout experience is ready for customers to use.
Now that you’re familiar with creating custom data fields and displaying dynamic content, you can start getting creative with the experiences you build within your product. Additionally, you can:
- Create a bookmark feature for courses.
- Add user profiles with a list of their purchased courses.
- Create a function to publish user reviews on course pages. We’ve previously covered this feature in our IMDB How To Build post.
Privacy & Security
Now that you have the basics of your app, don't forget to start setting some privacy rules and conditions to keep your data secure, starting with roles in the “Privacy” section of your Data tab. You can also check if you're unintentionally exposing any data with an API checker.
Hiring a developer or dev team to build this application would cost thousands, if not tens of thousands of dollars. As you launch and grow in users, our paid plans allow you to host the product on your own custom domain, starting from as low as $25 per month. Some templates and plugins may cost more, but you can build all the functionality of LinkedIn Learning without any additional costs.
If you don’t want to build your LinkedIn Learning clone from scratch, you can purchase one of the templates made by our community members. Some similar templates include:
- Courses like Udemy by Zeroqode
- Cata.Log - Online Catalog by Zeroqode
- Marketly Full Marketplace by Zeroqode
Bubble can help you build a LinkedIn Learning clone or any other product you choose! It’s never been easier to build something incredible without having to code.
Ready to join the no-code movement? Register your free account here and get started today.
If you’d like additional help when building your product, our thriving community forum is a great place to source actionable advice and resources. Any maker is also encouraged to ask questions within the community to help empower them on their no-code journey.