Files
media-map/README.md
Danilo Reyes 96fcc2b9e8 init
2025-12-28 20:59:09 -06:00

5.2 KiB

Movie Map

A web application that visualizes the origin countries of your media collection from Radarr, Sonarr, and Lidarr, and tracks which foreign movies/shows you've watched.

Features

View 1: Collection Map

  • Visualizes all media in your *arr instances on a world map
  • Shows country of origin for each movie/show/artist
  • Color intensity indicates number of items per country
  • Filter by media type (movies, shows, music)
  • Pin markers show counts per country

View 2: Watched Map

  • Interactive map to track watched foreign movies and TV shows
  • Manually add watched items with country information
  • Add custom pins to mark countries
  • Visualize your personal "watched foreign media" journey

Architecture

  • Backend: FastAPI (Python) with PostgreSQL
  • Frontend: React + TypeScript + Vite + Leaflet
  • Database: PostgreSQL (via Unix socket)
  • Deployment: Nix flake with NixOS module

Development Setup

Prerequisites

  • Nix with flakes enabled
  • PostgreSQL running (accessible via socket)
  • Access to Radarr, Sonarr, Lidarr instances

Getting Started

  1. Enter the development shell:
nix develop
  1. Set up environment variables (create .env in backend/):
POSTGRES_SOCKET_PATH=/run/postgresql
POSTGRES_DB=jawz
POSTGRES_USER=jawz
SONARR_API_KEY=your_sonarr_api_key
RADARR_API_KEY=your_radarr_api_key
LIDARR_API_KEY=your_lidarr_api_key
PORT=8080
  1. Run database migrations:
cd backend
alembic upgrade head
  1. Start the backend (in one terminal):
cd backend
python -m uvicorn main:app --reload --host 127.0.0.1 --port 8080
  1. Start the frontend dev server (in another terminal):
cd frontend
npm install
npm run dev
  1. Open http://localhost:5173 in your browser

Building

Build the application using Nix:

nix build

This creates a combined package with both backend and frontend.

NixOS Deployment

1. Add the flake to your NixOS configuration

In your configuration.nix or a separate module:

{
  imports = [
    /path/to/movie-map/nixosModules.default
  ];

  services.moviemap = {
    enable = true;
    port = 8080;
    postgresSocketPath = "/run/postgresql";
    # Secrets can be strings or file paths (for sops-nix integration)
    sonarrApiKey = "/run/secrets/sonarr-api-key";  # or "your_key_here"
    radarrApiKey = "/run/secrets/radarr-api-key";   # or "your_key_here"
    lidarrApiKey = "/run/secrets/lidarr-api-key";  # or "your_key_here"
    # Optional: admin token for sync endpoint
    adminToken = "/run/secrets/moviemap-admin-token";  # or "your_token_here"
  };
}

Or reference the flake directly:

{
  imports = [
    (builtins.getFlake "/path/to/movie-map").nixosModules.default
  ];
  
  services.moviemap = {
    enable = true;
    # ... configuration
  };
}

2. Run database migrations

Before starting the service, run migrations. You can do this either:

Option A: Run migrations manually before enabling the service

# SSH into your server
ssh server

# Enter the flake shell
cd /path/to/movie-map
nix develop

# Run migrations
cd backend
alembic upgrade head

Option B: Add a systemd service to run migrations on first start

You can add a one-shot systemd service that runs migrations before the main service starts. Add this to your NixOS configuration:

systemd.services.moviemap-migrate = {
  description = "Movie Map Database Migrations";
  serviceConfig = {
    Type = "oneshot";
    User = "moviemap";
    WorkingDirectory = "${appPackage}/backend";
    ExecStart = "${pythonEnv}/bin/alembic upgrade head";
  };
  before = [ "moviemap-backend.service" ];
  requiredBy = [ "moviemap-backend.service" ];
};

Or simply run migrations once manually, then enable the service.

3. Rebuild and enable

sudo nixos-rebuild switch

The service will be available at http://127.0.0.1:8080 (configure your reverse proxy to expose it).

API Endpoints

Collection

  • GET /api/collection/summary?types=movie,show,music - Get collection summary by country

Watched Items

  • GET /api/watched - List all watched items
  • GET /api/watched/summary - Get watched summary by country
  • POST /api/watched - Create watched item
  • PATCH /api/watched/{id} - Update watched item
  • DELETE /api/watched/{id} - Delete watched item

Pins

  • GET /api/pins - List all manual pins
  • POST /api/pins - Create pin
  • DELETE /api/pins/{id} - Delete pin

Admin

  • POST /admin/sync - Trigger sync from all *arr instances (requires admin token if configured)

Database Schema

The application creates a moviemap schema in the jawz database with the following tables:

  • source - *arr instance configuration
  • media_item - Normalized media items from *arr
  • media_country - Country associations for media items
  • watched_item - User-tracked watched items
  • manual_pin - Custom pins on the map

Country Extraction

The sync process extracts country information from *arr metadata:

  • Radarr: Uses productionCountries from movie metadata
  • Sonarr: Uses originCountry from series metadata (if available)
  • Lidarr: Uses country field from artist metadata

If country information is not available, the item is stored without a country association (excluded from map visualization).

License

MIT