# OfflineAcademy

A self-hosted, LAN-first video course library for private learning.

Turn a local folder of course videos into a clean learning dashboard with progress tracking, bookmarks, tags, categories, and optional AI-generated quizzes.

Next.js React TypeScript Prisma Docker

--- ## Table of Contents - [Why OfflineAcademy?](#why-offlineacademy) - [Feature Highlights](#feature-highlights) - [Screenshots](#screenshots) - [Tech Stack](#tech-stack) - [Quick Start](#quick-start) - [Docker Deployment](#docker-deployment) - [Configuration](#configuration) - [Course Folder Structure](#course-folder-structure) - [Data & Persistence](#data--persistence) - [Updating](#updating) - [Backup](#backup) - [Security Notes](#security-notes) - [License](#license) --- ## Why OfflineAcademy? Most online course platforms assume cloud storage, user accounts, subscriptions, and constant internet access. OfflineAcademy is built for a different workflow: - You already have course videos stored locally. - You want a clean interface to browse, watch, and resume lessons. - You want progress tracking without uploading your learning data anywhere. - You want a private LAN app that works from your desktop, laptop, tablet, or phone. - You want optional quiz practice without turning the app into a cloud product. OfflineAcademy is designed for **single-user local/LAN deployments**: home servers, NAS boxes, mini PCs, Docker hosts, homelabs, and personal workstations. --- ## Feature Highlights ### Course Library - Scan a local course directory and build a browsable library. - Display course cards with progress, metadata, tags, categories, and quick actions. - Pin/favorite important courses. - Rename courses from the UI. - **Delete from library** to hide/archive without deleting files. - **Delete from disk** when you intentionally want to remove course files. - Unified action menus across dashboard and course pages. ### Video Learning Experience - Browser-based playback for local video files. - Resume playback from the last watched position. - Track lesson progress automatically. - Continue watching card for the most recent lesson. - Mobile-friendly controls and responsive layout. - Playback speed controls. - Fullscreen and picture-in-picture support where supported by the browser. - Keyboard shortcuts overlay. ### Bookmarks & Learning Notes - Bookmark lessons for later review. - Store bookmark notes alongside lessons. - Revisit saved moments without hunting through folders manually. ### Course Organization - Add custom tags to courses. - Add categories to courses. - Filter and search the course library. - Keep all organization metadata local to the app/database. ### AI Quiz Practice - Generate module-level practice quizzes. - Supports QuizAPI and The Trivia API. - Per-video quiz topic overrides. - Clear or regenerate quizzes from course actions. - Smart skip logic for low-value quiz targets: - introductions - footnotes - appendices - bonus lectures - modules without useful quiz topics - Graceful fallback handling when providers rate-limit or lack matching categories. ### Offline & Local-First Design - No accounts. - No user profiles. - No required cloud storage. - Local SQLite database via Prisma. - Offline-capable PWA behavior through service worker caching. - Machine-scoped settings from the app UI. ### Deployment-Friendly - Local Node.js deployment. - Docker and Docker Compose support. - Portable folder mounts for courses and database. - Suitable for trusted LAN/homelab environments. --- ## Screenshots ### Dashboard Browse courses, continue the most recent lesson, filter your library, and see learning stats at a glance. ![OfflineAcademy dashboard](docs/screenshots/dashboard.png) ### Course Page View course progress, modules, lessons, and quick actions from a focused course detail page. ![OfflineAcademy course page](docs/screenshots/course-page.png) ### Watch Page Watch lessons with progress tracking, course navigation, and bookmark notes in one place. ![OfflineAcademy watch page](docs/screenshots/watch-page.png) ### Settings Configure the course directory, quiz provider, auto-fetch behavior, and API key from the local settings page. ![OfflineAcademy settings page](docs/screenshots/settings.png) --- ## Tech Stack ```text Frontend Next.js 14, React 18, TypeScript Styling Tailwind CSS, Radix UI Database SQLite ORM Prisma Runtime Node.js Deploy Docker / Docker Compose or local Node.js ``` --- ## Quick Start ### Prerequisites - Node.js 18+ recommended - npm - A folder containing your course videos ### 1. Clone the repository ```bash git clone https://github.com/YOUR_USERNAME/offlineacademy.git cd offlineacademy ``` ### 2. Create your environment file ```bash cp .env.example .env ``` Edit `.env` if needed: ```env DATABASE_URL="file:./dev.db" COURSES_ROOT="./My_Courses" NEXT_PUBLIC_APP_URL="http://localhost:6767" QUIZAPI_KEY="" ``` ### 3. Install dependencies ```bash npm ci ``` ### 4. Prepare the database ```bash npx prisma generate npx prisma db push ``` ### 5. Add courses Create a course folder: ```bash mkdir -p My_Courses ``` Place your course folders inside `My_Courses`. ### 6. Build and run ```bash npm run build npx next start -p 6767 ``` Open: ```text http://localhost:6767 ``` --- ## Docker Deployment Docker is the recommended deployment path for most users. ### Option A: Use the Docker Hub image OfflineAcademy is published on Docker Hub: ```text https://hub.docker.com/r/nicetry247/offlineacademy ``` Available image tags: ```text nicetry247/offlineacademy:latest nicetry247/offlineacademy:1.0.0 ``` Users can run OfflineAcademy without building from source: ```bash mkdir -p offlineacademy/My_Courses offlineacademy/prisma cd offlineacademy curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/nicetry247/offlineacademy/main/docker-compose.hub.yml curl -fsSL -o .env https://raw.githubusercontent.com/nicetry247/offlineacademy/main/.env.example touch prisma/dev.db docker compose pull docker compose up -d ``` Or pull the image directly: ```bash docker pull nicetry247/offlineacademy:latest ``` Open: ```text http://localhost:6767 ``` For LAN access, replace `localhost` with your server IP: ```text http://YOUR_SERVER_IP:6767 ``` ### Option B: Build locally from source ```bash git clone https://github.com/nicetry247/offlineacademy.git cd offlineacademy cp .env.example .env mkdir -p My_Courses prisma touch prisma/dev.db docker compose up --build -d ``` ### Custom Course Folder You can store courses anywhere on the host. Update your Compose file and map your folder to `/app/My_Courses` inside the container: ```yaml volumes: - /path/to/your/courses:/app/My_Courses - ./prisma/dev.db:/app/prisma/dev.db ``` Examples: ```yaml # Linux - /mnt/media/courses:/app/My_Courses # macOS - /Users/you/Videos/Courses:/app/My_Courses # Windows with Docker Desktop - C:/Users/you/Videos/Courses:/app/My_Courses ``` ### Publishing to Docker Hub Maintainers can publish manually: ```bash docker login docker build -t nicetry247/offlineacademy:latest . docker push nicetry247/offlineacademy:latest ``` You can also automate Docker Hub publishing later with GitHub Actions. To do that, add repository secrets for: ```text DOCKERHUB_USERNAME DOCKERHUB_TOKEN ``` Then add a workflow that builds and pushes `nicetry247/offlineacademy:latest` on pushes to `main` and version tags like `v1.0.0`. --- ## Configuration | Variable | Required | Purpose | Example | |---|---:|---|---| | `DATABASE_URL` | Yes | SQLite database path | `file:./dev.db` | | `COURSES_ROOT` | Yes | Course folder path inside the app/container | `./My_Courses` | | `NEXT_PUBLIC_APP_URL` | Recommended | Public app URL used by metadata and links | `http://localhost:6767` | | `QUIZAPI_KEY` | Optional | QuizAPI key for quiz generation | `qa_...` | Settings can also be managed inside the app at: ```text /settings ``` --- ## Course Folder Structure OfflineAcademy works best when courses are organized as folders containing module folders and video files. ```text My_Courses/ └── Example Course/ ├── 01 - Introduction/ │ └── 01 - Welcome.mp4 ├── 02 - Core Concepts/ │ ├── 01 - Lesson One.mp4 │ └── 02 - Lesson Two.mp4 └── 03 - Practice/ └── 01 - Lab Walkthrough.mp4 ``` Supported video extensions include common browser-playable formats such as `.mp4`, plus additional local media formats depending on browser support. --- ## Data & Persistence OfflineAcademy stores app data locally. ```text SQLite database prisma/dev.db Course files My_Courses/ or your configured course mount Environment .env Quiz cache Course/module folders where generated ``` Important user data: - watch progress - bookmarks - bookmark notes - course metadata - tags and categories - quiz records/cache - local app settings --- ## Updating ### Local Node.js ```bash git pull npm ci npx prisma generate npx prisma db push npm run build npx next start -p 6767 ``` ### Docker ```bash git pull docker compose up --build -d ``` --- ## Backup Back up these items regularly: ```text prisma/dev.db Main SQLite database .env Local configuration and optional API key My_Courses/ Your source course library, if not backed up elsewhere ``` A simple backup can be as easy as copying `prisma/dev.db` somewhere safe before updates. --- ## Security Notes OfflineAcademy is designed for trusted local networks and personal/homelab use. Before exposing it to the public internet, add: - HTTPS - reverse proxy authentication - network access controls - regular database backups - careful handling of `.env` and API keys Do not commit `.env`, local databases, course files, or private API keys. --- ## License OfflineAcademy is released under the **MIT License**. You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software, subject to the terms of the MIT License. See [`LICENSE`](LICENSE) for the full license text.