mirror of
https://github.com/nicetry247/offlineacademy.git
synced 2026-08-21 07:47:32 +00:00
initial commit
This commit is contained in:
@@ -0,0 +1,414 @@
|
||||
# OfflineAcademy
|
||||
|
||||
<p align="center">
|
||||
<strong>A self-hosted, LAN-first video course library for private learning.</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Turn a local folder of course videos into a clean learning dashboard with progress tracking, bookmarks, tags, categories, and optional AI-generated quizzes.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Next.js" src="https://img.shields.io/badge/Next.js-14-black?logo=nextdotjs" />
|
||||
<img alt="React" src="https://img.shields.io/badge/React-18-61DAFB?logo=react&logoColor=black" />
|
||||
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-5-3178C6?logo=typescript&logoColor=white" />
|
||||
<img alt="Prisma" src="https://img.shields.io/badge/Prisma-SQLite-2D3748?logo=prisma" />
|
||||
<img alt="Docker" src="https://img.shields.io/badge/Docker-ready-2496ED?logo=docker&logoColor=white" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
Add screenshots here after cloning or publishing the repository.
|
||||
|
||||
Recommended images:
|
||||
|
||||
```text
|
||||
docs/screenshots/dashboard.png
|
||||
docs/screenshots/course-page.png
|
||||
docs/screenshots/watch-page.png
|
||||
docs/screenshots/settings.png
|
||||
```
|
||||
|
||||
Example Markdown:
|
||||
|
||||
```md
|
||||

|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
|
||||
### 1. Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/offlineacademy.git
|
||||
cd offlineacademy
|
||||
```
|
||||
|
||||
### 2. Create `.env`
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
### 3. Create local folders
|
||||
|
||||
```bash
|
||||
mkdir -p My_Courses prisma
|
||||
touch prisma/dev.db
|
||||
```
|
||||
|
||||
### 4. Start the app
|
||||
|
||||
```bash
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
Open:
|
||||
|
||||
```text
|
||||
http://localhost:6767
|
||||
```
|
||||
|
||||
For LAN access, replace `localhost` with your server IP:
|
||||
|
||||
```text
|
||||
http://YOUR_SERVER_IP:6767
|
||||
```
|
||||
|
||||
### Custom Course Folder
|
||||
|
||||
You can store courses anywhere on the host. Update `docker-compose.yml` 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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||
No license has been selected yet.
|
||||
|
||||
That means the source is visible if this repository is public, but **all rights are reserved by default**. Other people do not automatically have permission to reuse, modify, redistribute, or sell the code.
|
||||
|
||||
If you want others to freely self-host, modify, and contribute to OfflineAcademy, consider adding an open-source license such as:
|
||||
|
||||
- **MIT** — simple and permissive
|
||||
- **Apache-2.0** — permissive with explicit patent language
|
||||
- **GPL-3.0** — requires derivative works to remain open-source
|
||||
|
||||
For a public portfolio project that may become a product later, keeping the license undecided is a reasonable temporary choice.
|
||||
Reference in New Issue
Block a user