This repository has been archived on 2026-06-15. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MediaLore/README.md
2026-03-25 16:24:14 -04:00

5.1 KiB

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+

# 1. Install dependencies
npm install

# 2. Start the development server
npm run dev

Open http://localhost:3000.

Other available commands:

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:

[
  {
    "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/<id>)
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=<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

Tech Stack