Development
This page explains how to run Polyfin from source, run its tests, refresh the Jellyfin fixtures, and work on the website.
Requirements
- Go 1.27.
- Node.js 24.
- A PostgreSQL 18 server.
- FFmpeg 9.0 or later (
ffmpegandffprobe), to play titles.
With POSTGRES_PASSWORD set in .env, docker compose -f compose.yaml -f compose.build.yaml up -d postgres starts a PostgreSQL server on 127.0.0.1:5432.
Commands
export POLYFIN_DATABASE_URL=postgresql://polyfin:password@127.0.0.1:5432/polyfin
make dev # builds the admin app, then runs the server on :8096
npm --prefix web run dev # optional: admin app with hot reload, proxied to :8096
make check # formatting, vet and testsTests
- Database tests run when
POLYFIN_TEST_DATABASE_URLpoints to a disposable PostgreSQL database whose role may create databases. Most database tests work in a database of their own, copied from a template database migrated once and kept for later runs,polyfin_template_followed by a key of the migrations; the others work in a schema of their own. - Remux tests run when
POLYFIN_TEST_FFMPEGnames anffmpegexecutable withffprobebeside it. - CI always provides both.
make checkruns every package's tests under the race detector (make test), then, without it, the time bounds of a large IPTV line-up (make bounds): the race detector slows that work tenfold, and gets a tenth of the line-up. CI runs the tests ofinternal/jellyfin, by far the longest, in a job of their own (make test-jellyfin), and the others beside the rest of the checks (make test-others).- The tests of the slowest packages run in parallel. A test that changes state other tests read, such as a package variable, or that times waits of a few milliseconds, stays sequential and says why.
- The SMB share tests run when
POLYFIN_TEST_SMBnames a share holding video files, its user and password in the address:smb://user:password@host:port/share/folder. The user must be allowed to write there: the change notification test adds, renames and removes files in a folder of its own, removed after. CI does not run them; WebDAV folders are tested against a server in the tests themselves. make image-checkbuilds the image and checks the version it prints;make image-healththen starts it against the PostgreSQL ofIMAGE_DATABASE_URL, by default the host's on port 5432 with the user, password and databasepolyfin, and waits for its health check to report it healthy, as CI does.
Jellyfin fixtures
Jellyfin API responses are checked against the JSON structure of a real Jellyfin 12.2 server, recorded in internal/jellyfin/testdata/. Jellyfin 12.3 answers the same: recorded again from it with the same scripts, its answers differ only in identifiers, dates, timings and the encoded clips' bitrates, so the 12.2 recordings stand for both.
scripts/jellyfin-fixtures.sh records them again from a disposable Jellyfin container. It requires Docker, curl and jq.
Website
The website is built with VitePress from docs/:
- Each page of this documentation is one of its pages, under
/docs/, with the sidebar following the sections of the documentation's index. Links that leavedocs/open the file on GitHub. - The landing page is in
docs/.vitepress/theme/, and its videos indocs/public/videos/. - VitePress 1 asks for Vite 5, whose development server has security advisories fixed only in Vite 6.4.3.
docs/package.jsonoverrides it with Vite 6; the override can go once VitePress asks for a fixed Vite.
npm --prefix docs ci
npm --prefix docs run dev # the website on http://127.0.0.1:5173/polyfin/, with hot reload
npm --prefix docs run build # fails on a link to a page that does not exist
npm --prefix docs run format # formats the landing page's codeCI builds the website for each pull request that changes docs/. Each push of such a change to main publishes it on GitHub Pages (.github/workflows/pages.yml).