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
.ziparchive 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.jsonat 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
.zipfilename can be anything; the first.zipfound in the folder is used. - Cover art filenames are matched case-insensitively against
cover.*andwidecover.*. 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
- Next.js 15 (App Router)
- React 19
- TypeScript 5
- Tailwind CSS 4