Stop 22 · Build Portfolio ProjectsProjects · 12/15

LMS (Learning Management System)

Part of the Frontend Developer Roadmap

In short

You're using a learning platform right now. Building one teaches you progress tracking, quizzes and different roles for students and teachers, all things real products deal with daily.

A course platform with lessons, progress tracking and quizzes — directly relevant experience given you're using this very roadmap tool's UX pattern yourself.

The jaadu teaches simple shapes on a whiteboard to students on plastic chairs.

Think of it like this

Your coaching centre, on a website

The teacher uploads chapters and tests. Students attend, mark what they've finished and take tests. The register shows who's on track. An LMS is that coaching centre, minus the plastic chairs.

Watch it happen

Progress that's worked out, not stored

Student
Course page
Progress DB

GET progress

1/6The course page loads Riya's completed lesson ids: just l1.

The big ideas

What you need to know

Courses, modules, lessons

A clear nested structure. Proves you can model real data, not just flat lists.

Progress that's derived

Store which lessons are done, and calculate percentages from that. No numbers going out of sync.

Quizzes with feedback

Instant answers and explanations. Shows you can build interactive, stateful UI.

Student and instructor roles

Instructors create content, students consume it. Role-based UI plus server checks.

How it works

Build plan

  1. 1

    Data model

    Course, module, lesson, quiz, and a progress record per user.

  2. 2

    Course pages

    Course overview with a sidebar of lessons.

  3. 3

    Mark complete and resume

    Tick lessons off and jump to the next unfinished one.

  4. 4

    Quizzes

    Multiple choice with scoring and explanations.

  5. 5

    Instructor side

    Simple forms to add lessons and quizzes.

See it in code

Walk through the code

js
1// lessons: ordered array, completed: Set of lesson ids2function getProgress(lessons, completed) {3  const done = lessons.filter((l) => completed.has(l.id)).length;4  const percent = lessons.length ? Math.round((done / lessons.length) * 100) : 0;5  const next = lessons.find((l) => !completed.has(l.id)) ?? null;6  return { done, total: lessons.length, percent, next };7}8 9getProgress(10  [{ id: "l1" }, { id: "l2" }, { id: "l3" }],11  new Set(["l1"])12); // { done: 1, total: 3, percent: 33, next: { id: "l2" } }

1/4Count how many lessons are in the completed set.

Only the completed ids are stored. Percent and the next lesson are worked out from them, so they can never disagree with each other.

Save yourself the pain

Common mistakes

Oops

Saving progress percent in the database as well as completed lessons.

Do this instead

Store only what's done and derive the rest. Two sources of truth always drift apart.

Oops

Building the instructor panel, video upload and payments before a student can finish one course.

Do this instead

Get one student flow working end to end first. Then add the extra roles and features.

Your mission

Milestone 1: finish one course

~45 min

Quick check

Why derive the progress percent instead of storing it?

Go deeper

  1. 1Model courses as nested data: course → modules → lessons.
  2. 2Implement progress tracking that persists per user (localStorage or backend).
  3. 3Add a simple quiz feature with scoring, similar to your earlier Quiz project.

More projects at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge