# 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
![OfflineAcademy dashboard](docs/screenshots/dashboard.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.

### 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.
