MediaManager Help

Developer Guide

This section is for those who want to contribute to Media Manager or understand its internals.

Source Code directory structure

  • media_manager/: Backend FastAPI application

  • web/: Frontend SvelteKit application

  • Writerside/: Documentation

  • metadata_relay/: Metadata relay service, also FastAPI

Special Dev Configuration

Env Variables

  • BASE_PATH: this sets the base path for the app (can be set for both backend and frontend)

  • PUBLIC_VERSION: this sets the version variable, it is displayed in the frontend (requires rebuilding of the frontend) and in the /api/v1/health endpoint (can be set for both backend and frontend)

  • FRONTEND_FILES_DIR: directory for frontend files, e.g. in Docker container it is /app/web/build (only backend)

Contributing

  • Consider opening an issue to discuss changes before starting work

Setting up the Development Environment

I use IntellijIdea with the Pycharm and Webstorm plugins to develop this, but this guide should also work with VSCode. Normally I'd recommend Intellij, but unfortunately only Intellij Ultimate has support for FastAPI and some other features.

  • Python

  • Svelte for VSCode

  • and probably more, but I don't use VSCode myself, so I can't recommend anymore.

  • Python

  • Svelte

  • Pydantic

  • Ruff

  • VirtualKit

  • Writerside (for writing documentation)

Other recommendations

I recommend developing using Docker, i.e. you can use the provided docker-compose.dev.yaml file. This dev docker-compose file has the ./media_manager directory mounted at /app/media_manager in the container, meaning you can run the code using the container in exactly the environment it will be running in.

Additionally, to develop the frontend I use a locally installed Node.js server. So basically a hybrid approach, where the backend runs in a container and the frontend runs on Windows. To make this work, you need to make sure the cors_urls and frontend_url are set correctly in the backend's config file.

Unfortunately, a side effect of this setup is that you have to rebuild the Docker image every time when you change the python dependencies in any way or at least restart the container if you change the code. For a fast-paced development it may be more convenient to run the backend locally too, because then it supports hot reloading.

Setting up the basic development environment with Docker

  • Copy the config.dev.toml file to config.toml in the ./res directory and edit it to your needs.

  • Use the following command to start the development environment with Docker:

    docker compose -f docker-compose.dev.yaml up -d

Setting up the backend development environment

  1. Clone the repository

  2. cd into repo root

  3. Install uv.

  4. run uv --version to verify that uv is installed correctly

  5. Install python if you haven't already:

    uv python install 3.13
  6. Create a virtual environment with uv

    uv venv --python 3.13
  7. Install dependencies:

    uv sync
  8. run db migrations with

    uv run alembic upgrade head
  9. run the backend with

    uv run ./media_manager/main.py --reload --port 8000
  • format code with uvx ruff format

  • lint code with uvx ruff check

Setting up the frontend development environment

  1. Clone the repository

  2. cd into repo root

  3. cd into web directory

  4. install Node.js and npm if you haven't already, I used nvm-windows:

    nvm install 24.1.0 nvm use 24.1.0

    I also needed to run the following command to be able to use npm:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
  5. Install the dependencies with npm: npm install

  6. Start the frontend development server: npm run dev

  • format the code with npm run format

  • lint the code with npm run lint

Sequence Diagrams

SchedulerQBittorrentTorrent ServiceIndexer ServiceDatabaseFile SystemMetadataProviderServiceTV ServiceTV RouterUserSchedulerQBittorrentTorrent ServiceIndexer ServiceDatabaseFile SystemMetadataProviderServiceTV ServiceTV RouterUserThis associates a season with a torrent id and the file_path_suffixHourly scheduler triggerif a torrent is finished downloading it will be importedExtracts archives, guesses mimetype (Video/Subtitle/Other)filters files based on some regex and renames themUser can now access the show in e.g. JellyfinAdd a show (POST /tv/shows)Receive Show RequestGet Metadata for ShowSave Poster ImageStore show informationGet Available Torrents for a Season (GET /tv/torrents)Receive RequestSearch for torrentsReturns Public Indexer ResultsDownload Torrent (POST /tv/torrents)Receive RequestSaves a SeasonFile objectDownload TorrentSave TorrentfileDownload Torrentauto_import_all_show_torrents()Get all Shows and seasons which are associated with a torrentUpdate Torrent download statusesget all files in the torrents directoryMove/Hardlink video and subtitle filesStep-by-step: going from adding a show to importing a torrent of one of its seasons

Tech Stack

Backend

  • Python with FastAPI

  • SQLAlchemy

  • Pydantic and Pydantic-Settings

  • Alembic

Frontend

  • TypeScript with SvelteKit

  • Tailwind CSS

  • shadcn-svelte

CI/CD

  • GitHub Actions

18 July 2025