add library management
This commit is contained in:
49
README.md
49
README.md
@@ -6,27 +6,30 @@ A self-hosted web UI for browsing media libraries on a NAS or local filesystem.
|
||||
|
||||
- **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.
|
||||
- **Library management UI** — add and remove libraries at `/manage` without touching any config files. Configuration persists across restarts in `libraries.json`.
|
||||
- **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
|
||||
├── libraries.json # Runtime library config (managed via UI, do not edit by hand)
|
||||
├── data/ # Example media (not committed to production)
|
||||
├── src/
|
||||
│ ├── app/
|
||||
│ │ ├── layout.tsx
|
||||
│ │ ├── page.tsx # Home — library cards
|
||||
│ │ ├── page.tsx # Home — library cards (redirects to /manage if empty)
|
||||
│ │ ├── manage/page.tsx # Library management — add/remove libraries
|
||||
│ │ ├── library/[id]/page.tsx # Library view (games or mixed)
|
||||
│ │ └── api/
|
||||
│ │ ├── libraries/route.ts # GET /api/libraries
|
||||
│ │ ├── libraries/route.ts # GET /api/libraries, POST /api/libraries
|
||||
│ │ ├── libraries/[id]/route.ts # DELETE /api/libraries/:id
|
||||
│ │ ├── 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
|
||||
│ │ ├── NavLink.tsx
|
||||
│ │ ├── games/
|
||||
│ │ │ ├── GamesView.tsx
|
||||
│ │ │ └── GameDetailModal.tsx
|
||||
@@ -35,7 +38,7 @@ MediaLoreWeb/
|
||||
│ │ ├── VideoPlayerModal.tsx
|
||||
│ │ └── ImageLightbox.tsx
|
||||
│ ├── lib/
|
||||
│ │ ├── libraries.ts # Config parsing and path resolution
|
||||
│ │ ├── libraries.ts # Config read/write, path resolution, add/remove helpers
|
||||
│ │ ├── games.ts # Games library scanner
|
||||
│ │ └── files.ts # Mixed library directory scanner
|
||||
│ └── types/
|
||||
@@ -66,33 +69,21 @@ npm run lint # Run ESLint
|
||||
|
||||
## Library Configuration
|
||||
|
||||
Libraries are defined in `libraries.json` at the project root:
|
||||
Libraries are managed through the **Manage Libraries** screen at `/manage` in the app. No manual file editing is required.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "games",
|
||||
"name": "Games",
|
||||
"path": "./data/Games",
|
||||
"type": "games"
|
||||
},
|
||||
{
|
||||
"id": "various",
|
||||
"name": "Various Media",
|
||||
"path": "./data/Various Media",
|
||||
"type": "mixed"
|
||||
}
|
||||
]
|
||||
```
|
||||
When you add a library via the UI, you provide:
|
||||
|
||||
| Field | Description |
|
||||
|--------|-------------|
|
||||
| `id` | URL-safe unique identifier used in routes (`/library/<id>`) |
|
||||
| `name` | Display name shown in the UI |
|
||||
| `path` | Absolute or project-relative path to the library root folder |
|
||||
| `type` | `"games"` or `"mixed"` |
|
||||
| Name | Display name shown in the UI |
|
||||
| Path | Absolute or project-relative path to the library root folder on disk |
|
||||
| Type | `Games` or `Mixed Media` |
|
||||
|
||||
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`.
|
||||
The app validates that the path exists as a directory before saving. Configuration is stored in `libraries.json` at the project root and persists across restarts.
|
||||
|
||||
If no libraries are configured, navigating to `/` automatically redirects to `/manage`.
|
||||
|
||||
Paths can point anywhere on the filesystem — they do not need to be inside the project directory.
|
||||
|
||||
## Library Folder Conventions
|
||||
|
||||
@@ -124,7 +115,9 @@ All API routes are server-side. File paths are never exposed in client-side stat
|
||||
|
||||
| Route | Method | Description |
|
||||
|-------|--------|-------------|
|
||||
| `/api/libraries` | GET | Returns the full library list from `libraries.json` |
|
||||
| `/api/libraries` | GET | Returns the full configured library list |
|
||||
| `/api/libraries` | POST | Adds a library. Body: `{ name, path, type }`. Validates the path exists. |
|
||||
| `/api/libraries/:id` | DELETE | Removes a library by id |
|
||||
| `/api/games?libraryId=<id>` | GET | Scans the games library and returns structured game entries |
|
||||
| `/api/browse?libraryId=<id>&path=<subpath>` | GET | Lists the contents of a directory within a mixed library |
|
||||
| `/api/file?libraryId=<id>&path=<relpath>` | GET | Streams a file; supports HTTP `Range` requests for seekable video playback |
|
||||
|
||||
Reference in New Issue
Block a user