Development Setup
Requirements
- Docker Engine with Docker Compose v2
- Just
- Git, Python 3,
jq,curl,unzip, and OpenSSL - Node.js 20.20.2 for the CI-matched client and end-to-end workflows (the client package also accepts
^20.19.0 || ^22.13.0 || >=24)
Rust server work uses Rust 1.88.0, pinned in rust-toolchain.toml and CI. The Jellyfin plugin builds in the pinned .NET SDK 10.0.401 container; a local .NET installation is not needed. Ruby 3.2.9 is needed only to build the Jekyll documentation site. mold is optional and only speeds up local Rust linking.
Start the development stack
git clone https://github.com/mhbxyz/OpenWatchParty.git
cd OpenWatchParty
just setup # install client development dependencies and configure Git hooks
just up # build and start Jellyfin and the session server
just up also downloads the pinned development media, installs File Transformation, builds the plugin, initializes Jellyfin, provisions local test users, and checks session-server health. The first media download needs network access and about 176 MB of disk space. See Testing for test commands and the first watch-party tutorial for a user walkthrough.
Sample movie library
The development stack downloads Wing It! (2023) and Sprite Fright (2021)
into the ignored media/dev/Movies/ directory and creates the Blender Open
Movies (Dev) library at /media/DevMovies. Pinned sizes and SHA-256 checksums
are verified, and subsequent starts reuse the local copies. Both films are
shared by Blender Studio under CC BY 4.0:
Wing It! and
Sprite Fright. The
separate MEDIA_DIR mount remains available for your own library.
Jellyfin is available at http://localhost:8096; the server health endpoint is http://localhost:3000/health and its WebSocket endpoint is ws://localhost:3000/ws.
Development authentication
The dev Compose file binds both services to loopback. With no JWT_SECRET, its default ALLOW_INSECURE_NO_AUTH=true starts the session server in unauthenticated local-development mode. For authenticated development and end-to-end runs, set a disposable secret in .env and use the same value for the server and plugin:
printf 'JWT_SECRET=%s\nALLOW_INSECURE_NO_AUTH=false\n' "$(openssl rand -base64 32)" >> .env
just up
just up configures the dev plugin to match the server mode and waits for the server health check. The three local Jellyfin accounts are testhost, testclient1, and testclient2; their default password is owp-dev-test. Override it with OWP_DEV_PASSWORD before first provisioning. These are development credentials only. Production Compose forces ALLOW_INSECURE_NO_AUTH=false; configure JWT authentication on both the plugin and server before use. See server configuration and deployment.
The automated Jellyfin configuration is stored under ignored infra/docker/dev/config-auto/. To recreate it, stop the stack with just down, remove only that directory, then run just up. Existing user passwords are not changed by provisioning.
Development logins
| Username | Password | Purpose |
|---|---|---|
testhost |
owp-dev-test |
Local administrator and host |
testclient1 |
owp-dev-test |
First guest |
testclient2 |
owp-dev-test |
Second guest |
These credentials are local only. just up creates missing accounts but does not change an existing password. If you change OWP_DEV_PASSWORD after provisioning, update the accounts in Jellyfin too.
First-Time Setup
After just up, sign in at http://localhost:8096/web/ as testhost, play a sample movie, then open the Watch Party button in the header. Use another browser profile to sign in as testclient1 and test room creation and joining. The illustrated first watch-party tutorial covers the host and guest flow.
Common commands
Use just to list all recipes and just <module> to list module recipes.
| Command | Purpose |
|---|---|
just up, just down, just status, just logs |
Start, stop, inspect, and follow the dev stack |
just dev |
Start the stack and follow logs |
just watch |
Restart Jellyfin when client JavaScript files change; needs inotifywait or fswatch |
just build plugin, just build server, just build image, just build all |
Build the plugin, local server, server image, or all components |
just test |
Run server, plugin, client, owpctl, and release-script checks |
just lint |
Run Rust/owpctl Clippy and client ESLint |
just fmt |
Format Rust code |
just e2e |
Start the dev stack and run Playwright end-to-end scenarios |
just setup |
Install client dependencies and configure Git hooks |
just clean |
Remove build artifacts |
just shell server, just shell jellyfin |
Open a shell in a development container |
The stack mounts the plugin output and client source. Rebuild the relevant artifact after changes; just rebuild cleans and builds all components, then recreates the services.
Repository map
src/clients/jellyfin-web/: JavaScript client, tests, and package manifestsrc/plugins/jellyfin/: Jellyfin plugin and .NET testssrc/server/: Rust session serversrc/owpctl/: Rust administration CLIinfra/just/andjustfile: build, test, lint, and development recipesinfra/docker/: development and production Compose files and server Dockerfiledocs/: product, operation, technical, and development documentation
Development Workflow
Rebuild after changes
just up builds the File Transformation plugin and Jellyfin plugin before starting the stack. For a clean rebuild after changes across multiple components, run:
just rebuild
For a focused plugin or client change, just build plugin recopies the client modules and rebuilds the plugin; restart Jellyfin to load the new assembly and assets. just build server builds a local release binary, while just build image rebuilds the development Docker image. To apply a rebuilt server image, recreate that Compose service:
docker compose -f infra/docker/dev/docker-compose.yml up -d --force-recreate session-server
just watch watches client source files and restarts Jellyfin automatically. Otherwise restart Jellyfin and hard-refresh the browser after a client or plugin change. Changes to Rust server source require a rebuilt image and recreated service.
Hot Reload
For client edits, keep just watch running and reload Jellyfin Web when the restart finishes. The watcher uses inotifywait or fswatch, with a polling fallback. Plugin and server code require rebuilding; just rebuild is the simplest reliable path.
Debugging
Check stack and server health first:
just status
curl -fsS http://localhost:3000/health
Follow logs with just logs server or just logs jellyfin; Jellyfin’s container log is also available with docker logs jellyfin-dev. For client errors, open the browser developer console and inspect the failed OpenWatchParty/ClientScript request. The plugin configuration page’s diagnostics can verify script injection, server reachability, and matching auth configuration.
For Rust diagnostics, run the server tests with RUST_BACKTRACE=1 just test server or use RUST_LOG=debug cargo run --manifest-path src/server/Cargo.toml for a local server process. Do not start a second local process on port 3000 while the Compose server is running.
Common Development Issues
Client script is not updating
Restart Jellyfin or allow just watch to do it, then hard-refresh the browser. Check that http://localhost:8096/OpenWatchParty/ClientScript responds and inspect the browser network panel for failed module requests.
Authentication mode mismatch
The dev plugin and session server must use the same JWT_SECRET and auth mode. just up provisions the plugin configuration from the environment and checks the server health endpoint; inspect .env and just logs server if startup reports a mismatch. Use the plugin diagnostics after changing configuration.
For deployment and browser-origin failures, see the Troubleshooting Guide.
Environment Variables
Create a root .env file to customize local development. Common values include:
JWT_SECRET=<disposable-base64-secret>
ALLOW_INSECURE_NO_AUTH=false
ALLOWED_ORIGINS=http://localhost:8096
LOG_LEVEL=debug
OWP_DEV_PASSWORD=<local-test-password>
Leave JWT_SECRET empty only for loopback-only unauthenticated development. Never reuse a production secret locally. See server configuration for all server settings.
See Contributing, Testing, and CI/CD for the contribution and validation workflow.