Skip to content

rheactdev/studynest

Repository files navigation

Course Player

A local-first course video player built with Next.js, SQLite, and a bold, compact UI courtesy of Boldkit. It scans a folder of downloaded courses, indexes sections, lessons, captions, attachments, and watch progress, then serves everything through stable ID-based routes.

Screenshots

2026-05-29 18 39 50 localhost 5293ca5b2fa0 2026-05-29 18 39 37 localhost e3adcaed4daa

Features

  • Local course library scanning into SQLite
  • Section and lesson navigation
  • HTML video playback with range requests
  • Resume position and completion tracking
  • Completed lessons shown with a success background and checkmark
  • Matching .vtt subtitle support, including language sidecars like intro.en.vtt
  • Lesson attachments matched from section folders or course-level attachment folders
  • Course covers and metadata support

Getting Started

Install dependencies:

pnpm install

Start the development server:

pnpm dev

Open http://localhost:3000.

Environment

The app reads courses and stores its database using these environment variables:

COURSES_DIR=./courses
DATA_DIR=./data
DATABASE_PATH=./data/course-player.sqlite

Defaults are shown above. You can put these in .env.local.

Course Folder Shape

Courses are discovered under an instructor folder:

courses/
  Instructor Name/
    Course Folder Name/
      cover.jpg
      00. Introduction/
        01. Welcome.mp4
        01. Welcome.en.vtt
      01. The Basics/
        01. Tutorial One.mp4
        02. Tutorial Two.mp4
      Attachments/
        01-01brush.abr
        01-01colorswatch.aco
        02-01character.psd

Section folders use a numeric prefix:

00. Introduction
01. The Basics

Lesson videos use a numeric prefix and one of these extensions:

01. Lesson Title.mp4
02. Lesson Title.mkv
03. Lesson Title.webm

Supported video extensions are mp4, mkv, webm, mov, and m4v.

Captions

Captions are matched beside the lesson video by filename:

01. Welcome.mp4
01. Welcome.vtt
01. Welcome.en.vtt

If multiple sidecar .vtt files exist, English sidecars such as .en.vtt are preferred.

Attachments

Course-level attachments use a section-lesson prefix. For example:

Attachments/
  1-1brush.abr

This attaches to section 01, lesson 01.

The scanner also supports section-local attachments:

01. The Basics/
  Attachments/
    01. Brush.abr
    01/
      Extra File.zip

Scanning

Start the app, then scan the course library:

curl -X POST http://localhost:3000/api/scan

After scanning, visit /courses and open a course.

Progress Tracking

Progress is stored in SQLite. The browser sends the current playback position and duration to the server:

  • every few seconds during playback
  • on pause
  • after seeking
  • when the tab is hidden
  • when the page exits
  • when the video ends

Lessons are marked complete when playback reaches 90% or the video ends.

Tags

Course tags are editable from the course detail page. Existing tags can be selected, and new tags can be created directly in the UI. Tags are stored in SQLite in courses.tags_json, and the scanner preserves existing user-created tags when a course is rescanned.

When deploying with Docker or Coolify, persist /app/data as a volume. Progress and course tags are both stored in the SQLite database there, so they survive container recreation.

Scripts

pnpm dev      # Start development server
pnpm build    # Build production app
pnpm start    # Start production server
pnpm lint     # Run ESLint

Tech Stack

  • Next.js 16
  • React 19
  • SQLite via node:sqlite
  • Tailwind CSS
  • Radix UI primitives
  • Lucide icons
  • BoldKit-inspired UI styling

Special Thanks

Special thanks to the BoldKit creator for making a beautiful UI and for being very helpful with issues.

About

Next.js course player that scans courses into SQLite, serves videos, captions, attachments, and tracks lesson progress.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages