From ff3cfe7ec3ce4fa91304445ad5b17dc1afc0c98b Mon Sep 17 00:00:00 2001 From: Garret Patti Date: Wed, 25 Mar 2026 16:24:14 -0400 Subject: [PATCH] add readme --- README.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b67636 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# MediaLore + +A self-hosted web UI for browsing media libraries on a NAS or local filesystem. Configure folders as typed libraries — currently supporting **Games** and **Mixed Media** library types. + +## Features + +- **Games library** — displays a grid of game cover art scanned from folders. Each game folder is expected to contain a `.zip` archive and optional artwork (`cover.*`, `widecover.*`). Clicking a game opens a detail modal with a download link for the zip. +- **Mixed media library** — a folder-navigable browser that mirrors the directory structure on disk. Videos open in an inline player (with full seek support via HTTP range requests). Images open in a lightbox. Other files are opened in a new tab. +- **Configurable libraries** — libraries are registered in `libraries.json` at the project root; no database required. +- **Path-jailed file serving** — all file access is verified to stay within the configured library root before being served. + +## Project Structure + +``` +MediaLoreWeb/ +├── libraries.json # Library configuration +├── data/ # Example media (not committed to production) +├── src/ +│ ├── app/ +│ │ ├── layout.tsx +│ │ ├── page.tsx # Home — library cards +│ │ ├── library/[id]/page.tsx # Library view (games or mixed) +│ │ └── api/ +│ │ ├── libraries/route.ts # GET /api/libraries +│ │ ├── games/route.ts # GET /api/games?libraryId= +│ │ ├── browse/route.ts # GET /api/browse?libraryId=&path= +│ │ └── file/route.ts # GET /api/file?libraryId=&path= +│ ├── components/ +│ │ ├── LibraryCard.tsx +│ │ ├── games/ +│ │ │ ├── GamesView.tsx +│ │ │ └── GameDetailModal.tsx +│ │ └── mixed/ +│ │ ├── MixedView.tsx +│ │ ├── VideoPlayerModal.tsx +│ │ └── ImageLightbox.tsx +│ ├── lib/ +│ │ ├── libraries.ts # Config parsing and path resolution +│ │ ├── games.ts # Games library scanner +│ │ └── files.ts # Mixed library directory scanner +│ └── types/ +│ └── index.ts +``` + +## Developer Setup + +**Requirements:** Node.js 18+ + +```bash +# 1. Install dependencies +npm install + +# 2. Start the development server +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +Other available commands: + +```bash +npm run build # Production build +npm run start # Start production server (run build first) +npm run lint # Run ESLint +``` + +## Library Configuration + +Libraries are defined in `libraries.json` at the project root: + +```json +[ + { + "id": "games", + "name": "Games", + "path": "./data/Games", + "type": "games" + }, + { + "id": "various", + "name": "Various Media", + "path": "./data/Various Media", + "type": "mixed" + } +] +``` + +| Field | Description | +|--------|-------------| +| `id` | URL-safe unique identifier used in routes (`/library/`) | +| `name` | Display name shown in the UI | +| `path` | Absolute or project-relative path to the library root folder | +| `type` | `"games"` or `"mixed"` | + +Paths can point anywhere on the filesystem — they do not need to be inside the project directory. Restart the dev server after editing `libraries.json`. + +## Library Folder Conventions + +### Games (`"type": "games"`) + +Each game is a subdirectory containing: + +``` +Games/ +└── My Game Title/ + ├── My Game Title.zip # Required — the downloadable archive + ├── cover.png # Optional — portrait cover art (case-insensitive) + └── widecover.jpg # Optional — landscape/hero cover art (case-insensitive) +``` + +- The `.zip` filename can be anything; the first `.zip` found in the folder is used. +- Cover art filenames are matched case-insensitively against `cover.*` and `widecover.*`. Any image extension is accepted. + +### Mixed Media (`"type": "mixed"`) + +No specific structure is required. The UI mirrors the directory tree exactly as it exists on disk. Supported media types: + +- **Video:** `.mp4`, `.mov`, `.mkv`, `.avi`, `.webm`, `.m4v` +- **Image:** `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.bmp`, `.tiff` + +## API Reference + +All API routes are server-side. File paths are never exposed in client-side state — only opaque `/api/file?...` URLs are sent to the browser. + +| Route | Method | Description | +|-------|--------|-------------| +| `/api/libraries` | GET | Returns the full library list from `libraries.json` | +| `/api/games?libraryId=` | GET | Scans the games library and returns structured game entries | +| `/api/browse?libraryId=&path=` | GET | Lists the contents of a directory within a mixed library | +| `/api/file?libraryId=&path=` | GET | Streams a file; supports HTTP `Range` requests for seekable video playback | + +## Tech Stack + +- [Next.js 15](https://nextjs.org/) (App Router) +- [React 19](https://react.dev/) +- [TypeScript 5](https://www.typescriptlang.org/) +- [Tailwind CSS 4](https://tailwindcss.com/)