2.18.0 (2026-03-15)
Breaking changes
Docker registry moved to GHCR and image names changed. The migrate service has been removed — migrations now run automatically inside the job-server on startup.
AIO users: just update the image name to ghcr.io/fredrikburmester/streamystats-aio:latest.
Recommended: Copy the latest docker-compose.yml from the repo. If you prefer to update manually, apply this diff:
services:
- migrate:
- image: docker.io/fredrikburmester/streamystats-v2-migrate:${VERSION:-latest}
- environment:
- - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@vectorchord:5432/${POSTGRES_DB:-streamystats}
- - POSTGRES_USER=${POSTGRES_USER:-postgres}
- - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres}
- - POSTGRES_DB=${POSTGRES_DB:-streamystats}
- - PGPASSWORD=${POSTGRES_PASSWORD:-postgres}
- depends_on:
- vectorchord:
- condition: service_healthy
- restart: "no"
-
nextjs-app:
- image: docker.io/fredrikburmester/streamystats-v2-nextjs:${VERSION:-latest}
+ image: ghcr.io/fredrikburmester/streamystats-nextjs:${VERSION:-latest}
depends_on:
vectorchord:
condition: service_healthy
- migrate:
- condition: service_completed_successfully
job-server:
condition: service_healthy
job-server:
- image: docker.io/fredrikburmester/streamystats-v2-job-server:${VERSION:-latest}
+ image: ghcr.io/fredrikburmester/streamystats-job-server:${VERSION:-latest}
depends_on:
vectorchord:
condition: service_healthy
- migrate:
- condition: service_completed_successfullyFeatures
- Mark items as played/unwatched with optional watchtime inference
- Wrapped design for yearly stats
- Internal/external URL support for Jellyfin servers behind reverse proxies
- Improved global search (series/movies prioritized over episodes)
- OpenRouter as AI provider
- Watchlist external API (CRUD via MediaBrowser auth)
- Per-server timezone support
- "Title Count" aggregation for people stats
- Clickable library statistics cards
- Improved genre radar chart readability
- CORS headers on recommendations endpoint
Bug Fixes
- Enforce Jellyfin library access restrictions for non-admin users
- Add DeviceId to Jellyfin auth headers for multi-device sessions
- Migrate Jellyfin API calls to MediaBrowser auth header
- Fix Voyage AI embedding provider configuration
- Fix embedding config not loading from DB for scheduled jobs
- Filter deleted items in "Almost Done" to prevent duplicate episodes
- Fix watch time duration formatting in charts
- Fix Jellystat import missing startTime/endTime
- Fix duplicate sessions on Playback Reporting import
- Allow local IPs for private Jellyfin servers (image proxy)
- Hide last played user from non-admin users
- Remove stale libraries during sync
- Stop false update notifications for Docker builds
- Add auth to previously unprotected API routes
- Add security middleware and input validation
- Fix basePath handling for reverse proxy setups
Infrastructure
- Docker images now published to
ghcr.io(no more Docker Hub rate limits) - Migration container removed — job-server handles migrations on startup
- Dependabot configured for npm, GitHub Actions, and Docker dependencies
- Trivy vulnerability scanner updated
- Security audit fixes for Docker and Next.js self-hosting