gpatti fe51f9f6c8
Some checks failed
Container Publish / backend (push) Failing after 1m43s
Container Publish / frontend (push) Failing after 9s
Merge pull request 'auth' (#4) from auth into main
Reviewed-on: #4
2026-08-03 20:12:03 +00:00
2026-06-29 10:41:29 -04:00
2026-06-29 10:41:29 -04:00
2026-06-29 10:41:29 -04:00
2026-06-29 10:41:29 -04:00
2026-07-29 07:22:18 -04:00
2026-06-29 10:41:29 -04:00
2026-08-03 15:11:42 -05:00
2026-06-28 16:54:51 -04:00

MediaLore

A self-hosted media library browser for images and videos. Organize your local media collections with tagged browsing, a file-system explorer, and a full-screen "doom scroll" viewer — all via a clean, responsive web UI.

Features

  • Media Libraries — Add local directories as named libraries; files are indexed by relative path within each library
  • File Browser — Navigate your library's directory structure with a thumbnail grid, breadcrumbs, and lazy-loaded previews
  • Tagging System — Organize media with named tags grouped into categories; create tags inline while viewing items
  • Search — Filter by filename (fuzzy match), tag, and/or library
  • Doom Scroll — Full-screen, swipe/scroll-driven media viewer for an immersive, social-media-like experience
  • Live File Watching — Automatically detects new, moved, and deleted files via watchdog (no manual rescans needed)
  • Auto-Generated Thumbnails — JPEG thumbnails for images (via Pillow) and videos (via ffmpeg)
  • Dark / Light Theme — Toggle with persistence via localStorage
  • Responsive — Mobile-friendly with a collapsible sidebar and touch gestures

Architecture

┌─────────────┐       ┌──────────────┐       ┌─────────────┐
│   Frontend   │──────▶│   Backend    │──────▶│   SQLite DB  │
│  React +     │  HTTP │  FastAPI +   │  ORM  │  (SQLite +   │
│  TypeScript  │       │  Uvicorn     │       │   WAL mode)  │
│  Vite        │       │              │       │              │
└─────────────┘       └──────┬───────┘       └─────────────┘
                             │
                     ┌───────▼────────┐
                     │  File System    │
                     │  (media root)   │
                     └─────────────────┘

Backend — Python 3.12+, FastAPI, SQLAlchemy (async), aiosqlite, Alembic for migrations, watchdog for file-system events, Pillow for image thumbnails, ffmpeg for video thumbnails.

Frontend — React 19, TypeScript, Vite 8, React Router 7, TanStack Query, Nginx (static serving + API proxy).

Quick Start (Docker Compose)

Prerequisites

  • Docker & Docker Compose
  • ffmpeg (bundled in the backend container)
  • Your media files accessible on the host (e.g. mounted from a NAS)

1. Clone & configure

git clone <repo-url>
cd MediaLore-Web-App
cp .env.example .env

Edit .env to point MEDIA_ROOT to your host media directory:

MEDIA_ROOT=/mnt/nas

Note: Inside the container, $MEDIA_ROOT maps to /media. Library paths you add in the UI must be subdirectories of this mount.

2. Start the stack

docker compose up --build -d

The frontend is available at http://localhost:8085.

3. Add a library

  1. Open SettingsLibraries
  2. Enter a name and a path (e.g. /media/Images/Photos)
  3. Click Add Library — scanning begins in the background

The scanner walks the directory tree, computes SHA-256 hashes, detects moved files by hash, and starts a file watcher for live updates.

Docker Compose Configuration

services:
  backend:
    build: ./backend
    volumes:
      - medialore-data:/data          # DB + thumbnails
      - /data/smb/adult/Images:/media/Images
      - /data/smb/adult/Video Clips:/media/Video Clips
    environment:
      - DATABASE_URL=sqlite+aiosqlite:////data/medialore.db
      - THUMBNAIL_DIR=/data/thumbnails

  frontend:
    build: ./frontend
    ports:
      - "8085:80"

Adjust the volume mounts to match your media layout. The medialore-data named volume persists the SQLite database and generated thumbnails across restarts.

API Endpoints

All endpoints are under /api and return JSON (except file/thumbnail responses).

Libraries

Method Path Description
GET /libraries List all libraries
POST /libraries Create a library ({ name, path })
GET /libraries/:id/scan-status Check if a library is currently scanning
POST /libraries/:id/rescan Trigger a manual rescan
GET /libraries/:id/browse Browse directory entries (?path=/sub/dir)
GET /libraries/:id/doom-scroll Get all media items in a library (optionally under a path)
DELETE /libraries/:id Remove a library (stops watcher, deletes records)

Media

Method Path Description
GET /media/:id Get media item details (with tags)
GET /media/:id/file Stream the original media file
GET /media/:id/thumbnail Get or generate a thumbnail (JPEG)
PUT /media/:id/tags Set tags on an item ({ tag_ids: [1, 2] })

Tags

Method Path Description
GET /tags List all tags grouped by category
POST /tags Create a tag ({ name, category })
DELETE /tags/:id Delete a tag
Method Path Description
GET /search?q=foo&tags=1,2&library_id=3 Search media by filename, tags, and/or library

Development

Backend (local)

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"   # or: pip install fastapi uvicorn[standard] sqlalchemy aiosqlite alembic pydantic-settings watchdog Pillow python-multipart
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Frontend (local)

cd frontend
npm install
npm run dev

The Vite dev server runs at http://localhost:5173. Configure your proxy or set VITE_API_BASE to point to the backend.

Data Model

┌──────────┐       1..*       ┌────────────┐       *..*       ┌─────┐
│ Library   │─────────────────▶│ MediaItem  │─────────────────▶│ Tag  │
└──────────┘                  └────────────┘                  └─────┘
  • id                          • id
  • name                        • library_id
  • path                        • rel_path
                                • filename
                                • file_hash   (SHA-256)
                                • media_type  (image | video)
                                • size_bytes
                                • missing     (file deleted from disk)
                                • created_at
                                • updated_at
                                • tags[]

Tech Stack

Layer Technology
Frontend React 19, TypeScript, Vite, React Router, TanStack Query
Backend Python 3.12+, FastAPI, Uvicorn
Database SQLite (async via aiosqlite, WAL mode)
Migrations Alembic
Thumbnails Pillow (images), ffmpeg (videos)
File Watching watchdog
Containerization Docker (Python 3.12-slim, Node 20-alpine, Nginx Alpine)

License

[Add your license here]

Description
No description provided
Readme 206 KiB
Languages
TypeScript 55.1%
Python 41.3%
CSS 1.2%
Dockerfile 0.6%
HTML 0.6%
Other 1.2%