Skip to content

Setting up RomM for development

Prerequisites

Tool Needed for
Python 3.14 or newer, pinned in .python-version
Node.js 24, with npm 11.10 or newer, per frontend/package.json
uv Dependencies, and it fetches the Python in .python-version
Docker For the database, Valkey, and the optional streaming stack

Option 1: Using Docker

You can run RomM for development with the provided Docker Compose configuration, which keeps all dependencies inside Docker containers.

Environment setup

Create the mock structure with at least one ROM and empty config for manual testing

mkdir -p romm_mock/library/roms/switch
touch romm_mock/library/roms/switch/metroid.xci
mkdir -p romm_mock/resources
mkdir -p romm_mock/assets
mkdir -p romm_mock/config
touch romm_mock/config/config.yml

Copy env.template to .env and fill the variables

cp env.template .env
ROMM_BASE_PATH=/app/romm
DEV_MODE=true

Build the image

docker compose build  # or `docker compose build --no-cache` to rebuild from scratch

Spin up the Docker containers

docker compose up -d

The app is then available at http://localhost:3000. The volume mounts reflect code changes in the app automatically.

Option 2: Manual setup

Environment setup

Create the mock structure with at least one ROM and empty config for manual testing

mkdir -p romm_mock/library/roms/switch
touch romm_mock/library/roms/switch/metroid.xci
mkdir -p romm_mock/resources
mkdir -p romm_mock/assets
mkdir -p romm_mock/config
touch romm_mock/config/config.yml

Copy env.template to .env and fill the variables

cp env.template .env

Install system dependencies

# https://mariadb.com/docs/skysql-previous-release/connect/programming-languages/c/install/#Installation_via_Package_Repository_(Linux):
sudo apt install libmariadb3 libmariadb-dev libpq-dev

# Build and configure RAHasher (optional)
# This is only required to calculate RA hashes
# Users on macOS can skip this step as RAHasher is not supported
git clone --recursive https://github.com/RetroAchievements/RALibretro.git
cd ./RALibretro
git checkout 1.8.3
git submodule update --init --recursive
make HAVE_CHD=1 -f ./Makefile.RAHasher
cp ./bin64/RAHasher /usr/bin/RAHasher

Install python dependencies

Install uv (see https://docs.astral.sh/uv/getting-started/installation/):

curl -LsSf https://astral.sh/uv/install.sh | sh

Then create the virtual environment and install the dependencies using uv:

uv venv
source .venv/bin/activate
uv sync --all-extras --dev

Spin up the database and other services

docker compose up -d

Two optional stacks have their own compose files:

docker compose -f docker-compose.oidc.yml up -d      # Authentik, for testing OIDC
docker compose -f docker-compose.streaming.yml up -d # webstation, for emulator streaming

The streaming image is amd64 only and runs to several GB, so it's opt-in.

Run the backend

Migrations will be run automatically when running the backend.

cd backend
uv run python3 main.py

Setting up the frontend

Install node.js dependencies

cd frontend
npm install
mkdir assets/romm
ln -s ../romm_mock/resources assets/romm/resources
ln -s ../romm_mock/assets assets/romm/assets

Run the frontend

npm run dev

Run the frontend against a remote RomM

Set DEV_PROXY_TARGET in the repo-root .env to another instance's origin, such as a home server with a full library:

DEV_PROXY_TARGET=https://romm.example.com

Vite then proxies /api, /ws, /netplay, /openapi.json, the EasyRPG player's game files and /assets/romm to that instance instead of the local backend, which you don't need to run. Leave it empty to keep the default http://127.0.0.1:${DEV_PORT}. The remote's TLS certificate must be valid. Sign in with a username and password, because OIDC doesn't work through the proxy: the identity provider redirects to the remote's OIDC_REDIRECT_URI, so the session never reaches localhost.

Setting up the linter

We use Trunk for linting, which combines multiple linters and formatters with sensible defaults and a single configuration file. You'll need to install the Trunk CLI to use it.

Install the Trunk CLI

curl https://get.trunk.io -fsSL | bash

Alternative installation methods can be found in their docs. On commit, the linter will run automatically. To run it manually, use the following commands:

trunk fmt
trunk check

Failing to install and run the linter will result in a failed CI check, which won't allow us to merge your PR.

Test setup

Create the test user and database with root user

docker exec -i romm-db-dev mariadb -uroot -p<root password> < backend/romm_test/setup.sql

Run tests

Migrations will be run automatically when running the tests.

cd backend
# path or test file can be passed as argument to test only a subset
uv run pytest [path/file]
# or run the following command to run all tests
# the -vv switch increases the verbosity of the output, providing more detailed information during test execution.
uv run pytest -vv