From 1f5ba31483c2d8d4438275359e57d07683560bfb Mon Sep 17 00:00:00 2001 From: s8n Date: Fri, 8 May 2026 02:57:34 +0100 Subject: [PATCH] =?UTF-8?q?Rename:=20nasflix=20=E2=86=92=20ARRFLIX=20+=20a?= =?UTF-8?q?pply=20Cineplex=20theme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Domain + repo rename: nasflix.s8n.ru → arrflix.s8n.ru, NASFLIX → ARRFLIX (Forgejo repo, Pi-hole DNS, Traefik file+label routes, compose env+labels, onyx /etc/hosts, branding LoginDisclaimer, all repo refs, logo asset). Theme: ElegantFin → Cineplex v1.0.6 (MRunkehl, pinned). Picked by research agent over JellyFlix (halted), DarkFlix (10.8.x only), Theme Park (no Netflix preset). Real #E50914 + Netflix Sans webfont + transform:scale hover + gradient login backdrop. Doc 04 updated with full candidate matrix, theme-history subsection, rollback-to-ElegantFin snippet. Logo asset saved at assets/logo.png (235x85 RGBA). Live: https://arrflix.s8n.ru → 302. tv.s8n.ru + nasflix.s8n.ru retired (404). --- ADMIN-GUIDE.md | 10 +- README.md | 6 +- ROADMAP.md | 6 +- assets/logo.png | Bin 0 -> 8496 bytes bin/add-jellyfin-user.sh | 2 +- docker-compose.yml | 6 +- docs/01-artwork-and-images.md | 4 +- docs/02-metadata-and-titles.md | 30 ++-- docs/03-subtitles.md | 18 +- docs/04-theming-and-users.md | 270 ++++++++++++++++++++---------- docs/05-file-structure-rules.md | 8 +- docs/06-per-library-themes.md | 6 +- docs/07-pre-import-cleanup.md | 6 +- docs/08-filename-normalization.md | 6 +- 14 files changed, 234 insertions(+), 144 deletions(-) create mode 100644 assets/logo.png diff --git a/ADMIN-GUIDE.md b/ADMIN-GUIDE.md index c54f61c..d86465a 100644 --- a/ADMIN-GUIDE.md +++ b/ADMIN-GUIDE.md @@ -1,4 +1,4 @@ -# Admin Guide — nasflix.s8n.ru +# Admin Guide — arrflix.s8n.ru The single page that tells you what to do and where to read more. Anything not on this page lives in `docs/` — links inline. @@ -15,7 +15,7 @@ What's next on this deploy → [`ROADMAP.md`](ROADMAP.md). | Config + cache | `nullstone:/home/docker/jellyfin/{config,cache}/` | | Media root | `nullstone:/home/user/media/{movies,tv}/` | | Traefik route | `/opt/docker/traefik/config/jellyfin-test.yml` (file-provider — see [docs/04 § routing-quirk](docs/04-theming-and-users.md)) | -| Pi-hole DNS pin | `/opt/docker/pihole/etc-pihole/custom.list` → `192.168.0.100 nasflix.s8n.ru` | +| Pi-hole DNS pin | `/opt/docker/pihole/etc-pihole/custom.list` → `192.168.0.100 arrflix.s8n.ru` | | User wrapper | `bin/add-jellyfin-user.sh` (always use this) | --- @@ -39,7 +39,7 @@ Why it exists (Jellyfin has no native global default) → see same doc. 3. Normalize filenames per [docs/08](docs/08-filename-normalization.md). Use `bin/normalize.py` once written. 4. Stage to `/home/admin/staging-jelly-/<canonical-name>/`. 5. `scp -r` to `nullstone:/home/user/media/<lib>/`. -6. Trigger refresh: `curl -X POST -H "Authorization: MediaBrowser Token=$TOKEN" https://nasflix.s8n.ru/Library/Refresh`. +6. Trigger refresh: `curl -X POST -H "Authorization: MediaBrowser Token=$TOKEN" https://arrflix.s8n.ru/Library/Refresh`. 7. Verify: hit the URL, check artwork + titles + episode counts. 8. **Only after confirmed working**: delete the source download + the staging dir. @@ -72,8 +72,8 @@ ElegantFin imports from `cdn.jsdelivr.net/gh/lscambo13/ElegantFin@main/...` — 1. **Wrapper-only user creation.** Don't create users in the Dashboard UI. Always run `bin/add-jellyfin-user.sh` so the layout + prefs are consistent. Doc 04. 2. **Stage before import.** Never drop raw downloads into `/home/user/media/`. Always clean + normalize first. Docs 05/07/08. 3. **Verify before delete.** Don't delete source downloads or old library entries until the new content is confirmed playing in the Jellyfin UI. -4. **No bind-mount drift.** If you change `docker-compose.yml`, commit + push to `git.s8n.ru/s8n/NASFLIX` in the same step. The repo is the source of truth for the deploy. Doc memory: `feedback_always_commit_to_my_git.md`. -5. **No public DNS.** `nasflix.s8n.ru` resolves only via Pi-hole locally. Do NOT add a Gandi A record. LAN-only is the threat model. +4. **No bind-mount drift.** If you change `docker-compose.yml`, commit + push to `git.s8n.ru/s8n/ARRFLIX` in the same step. The repo is the source of truth for the deploy. Doc memory: `feedback_always_commit_to_my_git.md`. +5. **No public DNS.** `arrflix.s8n.ru` resolves only via Pi-hole locally. Do NOT add a Gandi A record. LAN-only is the threat model. --- diff --git a/README.md b/README.md index cfaf111..32cc430 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NASFLIX +# ARRFLIX Self-hosted Jellyfin media server on nullstone, LAN-only. @@ -8,7 +8,7 @@ Self-hosted Jellyfin media server on nullstone, LAN-only. ## Endpoint -- `https://nasflix.s8n.ru` — accessible only from LAN (192.168.0.0/24) and Tailscale admin/infra tags via Traefik `no-guest@file` middleware. +- `https://arrflix.s8n.ru` — accessible only from LAN (192.168.0.0/24) and Tailscale admin/infra tags via Traefik `no-guest@file` middleware. - DNS resolved internally by Pi-hole (`/opt/docker/pihole/etc-pihole/custom.list`). - TLS via Let's Encrypt DNS-01 (Gandi). @@ -49,7 +49,7 @@ deploy: ## First-run setup -1. Browse to `https://nasflix.s8n.ru` from the LAN. +1. Browse to `https://arrflix.s8n.ru` from the LAN. 2. Create the admin user (Jellyfin onboarding wizard). 3. Add libraries pointing at `/media/movies` and `/media/tv` inside the container (these map to `/home/user/media/{movies,tv}`). diff --git a/ROADMAP.md b/ROADMAP.md index 40e216b..6b484c0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,4 +1,4 @@ -# Roadmap — NASFLIX +# Roadmap — ARRFLIX What's done, what's open, what's deferred. Update on every commit that lands or moves an item between buckets. @@ -9,7 +9,7 @@ Last revised: 2026-05-08 ## Done -- [x] **Deploy**: Jellyfin 10.10.3 on nullstone, LAN-only at `nasflix.s8n.ru`, file-provider Traefik route, LE cert via Gandi DNS-01, Pi-hole local DNS pin, userns_mode=host +- [x] **Deploy**: Jellyfin 10.10.3 on nullstone, LAN-only at `arrflix.s8n.ru`, file-provider Traefik route, LE cert via Gandi DNS-01, Pi-hole local DNS pin, userns_mode=host - [x] **Theme**: ElegantFin v25.12.31 applied via `/System/Configuration/branding` - [x] **Cast & Crew + Guest Stars**: hidden globally via CustomCss (`#castCollapsible, #guestCastCollapsible`) - [x] **Library**: TV Shows → `/media/tv/Futurama (1999)/`, 72 eps + 9 featurettes, locked to TMDB 615 @@ -40,7 +40,7 @@ Last revised: 2026-05-08 - Estimated wall: 30 min + reboot (nullstone hosts traefik, forgejo, matrix — ~2 min downtime) - [ ] **Loading-splash rebrand** - - Replace Jellyfin pre-bundle logo with `nasflix.s8n.ru` wordmark + 4-bar pulse spinner + - Replace Jellyfin pre-bundle logo with `arrflix.s8n.ru` wordmark + 4-bar pulse spinner - Approach: bind-mount patched `/jellyfin/jellyfin-web/index.html` per the plan in this session's history - Doc to write: `docs/09-loading-splash.md` (pre-bundle vs CustomCss timing, regen-on-upgrade) diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5de5f352b9af34b2f22c14fbb9dc1351de6db7eb GIT binary patch literal 8496 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 literal 0 HcmV?d00001 diff --git a/bin/add-jellyfin-user.sh b/bin/add-jellyfin-user.sh index 6b122cb..3d9a38b 100755 --- a/bin/add-jellyfin-user.sh +++ b/bin/add-jellyfin-user.sh @@ -19,7 +19,7 @@ # Or interactive (will prompt for missing creds). set -euo pipefail -JELLYFIN_URL="${JELLYFIN_URL:-https://nasflix.s8n.ru}" +JELLYFIN_URL="${JELLYFIN_URL:-https://arrflix.s8n.ru}" JELLYFIN_TOKEN="${JELLYFIN_TOKEN:?set JELLYFIN_TOKEN=<admin-token>}" USERNAME="${1:?usage: $0 <username> <password>}" diff --git a/docker-compose.yml b/docker-compose.yml index c439005..d7113e5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ # Jellyfin — self-hosted media server (LAN-only) # Deploy path on nullstone: /opt/docker/jellyfin/ -# Domain: nasflix.s8n.ru (LAN-only via Pi-hole local DNS + no-guest middleware) +# Domain: arrflix.s8n.ru (LAN-only via Pi-hole local DNS + no-guest middleware) # # Notes: # - GTX 1660 Ti present but nvidia-smi failing on host. CPU transcode only @@ -19,7 +19,7 @@ services: userns_mode: "host" environment: - TZ=Europe/London - - JELLYFIN_PublishedServerUrl=https://nasflix.s8n.ru + - JELLYFIN_PublishedServerUrl=https://arrflix.s8n.ru volumes: - /home/docker/jellyfin/config:/config - /home/docker/jellyfin/cache:/cache @@ -29,7 +29,7 @@ services: labels: - "traefik.enable=true" - "traefik.docker.network=proxy" - - "traefik.http.routers.jellyfin.rule=Host(`nasflix.s8n.ru`)" + - "traefik.http.routers.jellyfin.rule=Host(`arrflix.s8n.ru`)" - "traefik.http.routers.jellyfin.entrypoints=websecure" - "traefik.http.routers.jellyfin.tls=true" - "traefik.http.routers.jellyfin.tls.certresolver=letsencrypt" diff --git a/docs/01-artwork-and-images.md b/docs/01-artwork-and-images.md index b765324..92bdd28 100644 --- a/docs/01-artwork-and-images.md +++ b/docs/01-artwork-and-images.md @@ -5,14 +5,14 @@ wrong with the Futurama library on first scan, and the exact API calls used to fix it. Written for an operator who's never used Jellyfin before but is comfortable with curl and Docker. -Server: `https://nasflix.s8n.ru` (Jellyfin `10.10.3`, container `jellyfin` on +Server: `https://arrflix.s8n.ru` (Jellyfin `10.10.3`, container `jellyfin` on nullstone). Auth header below uses the long-lived API token — replace with your own `X-Emby-Token` if needed. ```bash TOKEN="*redacted*" H="-H \"Authorization: MediaBrowser Token=${TOKEN}\"" -BASE="https://nasflix.s8n.ru" +BASE="https://arrflix.s8n.ru" ``` --- diff --git a/docs/02-metadata-and-titles.md b/docs/02-metadata-and-titles.md index 52491f1..5f2c6fe 100644 --- a/docs/02-metadata-and-titles.md +++ b/docs/02-metadata-and-titles.md @@ -1,6 +1,6 @@ # Jellyfin Metadata & Episode Titles — Operator Guide -Server: `https://nasflix.s8n.ru` (Jellyfin 10.10.3, container on nullstone) +Server: `https://arrflix.s8n.ru` (Jellyfin 10.10.3, container on nullstone) Fixture for this doc: TV Shows library, series **Futurama** (1999), 44 episodes split across S01–S03. --- @@ -87,7 +87,7 @@ Jellyfin's Identify wizard has three calls. Auth header: `X-Emby-Token: <api-key ```bash curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"SearchInfo":{"Name":"Futurama"}}' \ - https://nasflix.s8n.ru/Items/RemoteSearch/Series + https://arrflix.s8n.ru/Items/RemoteSearch/Series ``` Returns an array of candidates from each registered provider (TheMovieDb, TheTVDB, OMDb). Inspect `ProviderIds`, `ProductionYear`, `Overview`, `ImageUrl` to pick the right one. @@ -97,14 +97,14 @@ For Episodes use `RemoteSearch/Episode` and pass `SeriesProviderIds` + `IndexNum ```bash curl -s --max-time 60 -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"Name":"Futurama","ProviderIds":{"Tmdb":"615"},"ProductionYear":1999,"SearchProviderName":"TheMovieDb"}' \ - "https://nasflix.s8n.ru/Items/RemoteSearch/Apply/$SERIES_ID?ReplaceAllImages=true" + "https://arrflix.s8n.ru/Items/RemoteSearch/Apply/$SERIES_ID?ReplaceAllImages=true" ``` Response: `204 No Content` on success. **Note**: this endpoint runs synchronously for ~30–60 s while Jellyfin pulls images. The Traefik proxy in front of Jellyfin will return `502 Bad Gateway` if you don't bump `--max-time` above the proxy's idle threshold. Use `--max-time 60` from the client; the operation continues server-side regardless of the client timeout. ### 4.3 Trigger a metadata refresh ```bash curl -s --max-time 60 -X POST -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items/$SERIES_ID/Refresh?Recursive=true&MetadataRefreshMode=FullRefresh&ImageRefreshMode=FullRefresh&ReplaceAllMetadata=true&ReplaceAllImages=false" + "https://arrflix.s8n.ru/Items/$SERIES_ID/Refresh?Recursive=true&MetadataRefreshMode=FullRefresh&ImageRefreshMode=FullRefresh&ReplaceAllMetadata=true&ReplaceAllImages=false" ``` Parameters: - `Recursive=true` — descend into seasons + episodes (otherwise only the series item refreshes) @@ -115,7 +115,7 @@ Parameters: The refresh is a fire-and-forget job. Poll for completion by re-querying episodes: ```bash curl -s -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items?Recursive=true&IncludeItemTypes=Episode&Fields=ProviderIds&ParentId=$SERIES_ID&Limit=44" \ + "https://arrflix.s8n.ru/Items?Recursive=true&IncludeItemTypes=Episode&Fields=ProviderIds&ParentId=$SERIES_ID&Limit=44" \ | jq '[.Items[] | select(.ProviderIds | length > 0)] | length' ``` @@ -134,7 +134,7 @@ curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ "PremiereDate":"1999-03-28", "LockedFields":["Name","Overview"] }' \ - https://nasflix.s8n.ru/Items/$EP_ID + https://arrflix.s8n.ru/Items/$EP_ID ``` `LockedFields` tells subsequent refreshes to leave those fields alone — important if you want to keep your override across future scans. @@ -165,7 +165,7 @@ TMDB falls back to English automatically when a Polish translation doesn't exist ```bash # Fetch current options -curl -s -H "X-Emby-Token: $TOKEN" https://nasflix.s8n.ru/Library/VirtualFolders \ +curl -s -H "X-Emby-Token: $TOKEN" https://arrflix.s8n.ru/Library/VirtualFolders \ | jq '.[] | select(.Name=="TV Shows") | .LibraryOptions' > opts.json # Modify in place (e.g. flip language to en) @@ -175,7 +175,7 @@ jq '.PreferredMetadataLanguage="en" | .MetadataCountryCode="US"' opts.json > opt LIB_ID=767bffe4f11c93ef34b805451a696a4e # TV Shows jq -n --arg id "$LIB_ID" --slurpfile o opts2.json '{Id:$id, LibraryOptions:$o[0]}' \ | curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ - -d @- "https://nasflix.s8n.ru/Library/VirtualFolders/LibraryOptions" + -d @- "https://arrflix.s8n.ru/Library/VirtualFolders/LibraryOptions" ``` Returns 204. **Side effect**: changing library options can trigger a container restart cycle on this Jellyfin install — saw it in our logs at the moment of update. Schedule this when no playback is active. @@ -198,7 +198,7 @@ For our Futurama set, all files are single-episode (`s01e01.pl.mkv`), so this di --- -## 8. The exact fix applied to Futurama on nasflix.s8n.ru (2026-05-08) +## 8. The exact fix applied to Futurama on arrflix.s8n.ru (2026-05-08) Step-by-step, with the exact commands run: @@ -208,35 +208,35 @@ SERIES_ID=156e57437f795e5c8cd80fc98bafaee0 # Futurama LIB_ID=767bffe4f11c93ef34b805451a696a4e # TV Shows library # 1. Pull current TV Shows options, flip EnableInternetProviders=true, post back. -curl -s -H "X-Emby-Token: $TOKEN" https://nasflix.s8n.ru/Library/VirtualFolders \ +curl -s -H "X-Emby-Token: $TOKEN" https://arrflix.s8n.ru/Library/VirtualFolders \ | jq '.[] | select(.Name=="TV Shows") | .LibraryOptions' > /tmp/opts.json jq '.EnableInternetProviders=true' /tmp/opts.json > /tmp/opts_new.json jq -n --arg id "$LIB_ID" --slurpfile o /tmp/opts_new.json \ '{Id:$id, LibraryOptions:$o[0]}' \ | curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ - -d @- https://nasflix.s8n.ru/Library/VirtualFolders/LibraryOptions + -d @- https://arrflix.s8n.ru/Library/VirtualFolders/LibraryOptions # -> 204 # 2. Search TMDB for Futurama (without provider hint to see all candidates). curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"SearchInfo":{"Name":"Futurama"}}' \ - https://nasflix.s8n.ru/Items/RemoteSearch/Series | jq '.[0]' + https://arrflix.s8n.ru/Items/RemoteSearch/Series | jq '.[0]' # -> first hit: TheMovieDb, Tmdb=615, PremiereDate=1999-03-28 (correct: original 1999 series) # 3. Apply that match to the series. curl -s --max-time 60 -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"Name":"Futurama","ProviderIds":{"Tmdb":"615"},"ProductionYear":1999,"SearchProviderName":"TheMovieDb"}' \ - "https://nasflix.s8n.ru/Items/RemoteSearch/Apply/$SERIES_ID?ReplaceAllImages=true" + "https://arrflix.s8n.ru/Items/RemoteSearch/Apply/$SERIES_ID?ReplaceAllImages=true" # -> 204 (after first attempt 502'd at proxy because client timeout was too low) # 4. Trigger recursive full refresh with replace-all metadata. curl -s --max-time 60 -X POST -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items/$SERIES_ID/Refresh?Recursive=true&MetadataRefreshMode=FullRefresh&ImageRefreshMode=FullRefresh&ReplaceAllMetadata=true&ReplaceAllImages=false" + "https://arrflix.s8n.ru/Items/$SERIES_ID/Refresh?Recursive=true&MetadataRefreshMode=FullRefresh&ImageRefreshMode=FullRefresh&ReplaceAllMetadata=true&ReplaceAllImages=false" # -> 204 # 5. Wait ~3 minutes, then verify episodes have providerids and Polish titles. curl -s -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items?Recursive=true&IncludeItemTypes=Episode&Fields=ProviderIds&ParentId=$SERIES_ID" \ + "https://arrflix.s8n.ru/Items?Recursive=true&IncludeItemTypes=Episode&Fields=ProviderIds&ParentId=$SERIES_ID" \ | jq '[.Items[] | select(.ProviderIds | length > 0)] | length' # -> 44/44 ``` diff --git a/docs/03-subtitles.md b/docs/03-subtitles.md index 892824c..f371ba0 100644 --- a/docs/03-subtitles.md +++ b/docs/03-subtitles.md @@ -1,8 +1,8 @@ -# 03 — Subtitles on Jellyfin (nasflix.s8n.ru) +# 03 — Subtitles on Jellyfin (arrflix.s8n.ru) Last updated: 2026-05-08 Server: Jellyfin 10.10.3 (X64) on nullstone, container `jellyfin` -URL: <https://nasflix.s8n.ru> +URL: <https://arrflix.s8n.ru> Use-case: Futurama (44 episodes), Polish audio, no embedded subs, automatic English subtitles required. --- @@ -67,7 +67,7 @@ When the server is upgraded to 10.11.x, switch to v24 via: ```bash curl -s -X POST -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Packages/Installed/Open%20Subtitles?AssemblyGuid=4b9ed42f-5185-48b5-9803-6ff2989014c4&Version=24.0.0.0&RepositoryUrl=https%3A%2F%2Frepo.jellyfin.org%2Ffiles%2Fplugin%2Fmanifest.json" + "https://arrflix.s8n.ru/Packages/Installed/Open%20Subtitles?AssemblyGuid=4b9ed42f-5185-48b5-9803-6ff2989014c4&Version=24.0.0.0&RepositoryUrl=https%3A%2F%2Frepo.jellyfin.org%2Ffiles%2Fplugin%2Fmanifest.json" docker restart jellyfin ``` @@ -97,12 +97,12 @@ PASS='your-opensubtitles-com-password' # 1. Validate (returns 200 on success, 401 on bad creds) curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d "{\"Username\":\"$USER\",\"Password\":\"$PASS\"}" \ - "https://nasflix.s8n.ru/Jellyfin.Plugin.OpenSubtitles/ValidateLoginInfo" -w "\nHTTP %{http_code}\n" + "https://arrflix.s8n.ru/Jellyfin.Plugin.OpenSubtitles/ValidateLoginInfo" -w "\nHTTP %{http_code}\n" # 2. Persist into plugin config curl -s -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d "{\"Username\":\"$USER\",\"Password\":\"$PASS\",\"CredentialsInvalid\":false}" \ - "https://nasflix.s8n.ru/Plugins/4b9ed42f-5185-48b5-9803-6ff2989014c4/Configuration" -w "\nHTTP %{http_code}\n" + "https://arrflix.s8n.ru/Plugins/4b9ed42f-5185-48b5-9803-6ff2989014c4/Configuration" -w "\nHTTP %{http_code}\n" ``` Or via UI: `Dashboard → Plugins → Open Subtitles → Settings`. @@ -167,7 +167,7 @@ EP=2b73bc176fbf8a02bb9bea9015ec13c6 # Query providers curl -s -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items/$EP/RemoteSearch/Subtitles/eng" | jq . + "https://arrflix.s8n.ru/Items/$EP/RemoteSearch/Subtitles/eng" | jq . # Returns array of SubtitleInfo objects: Id, ProviderName, Format, Comment, IsHashMatch, ... # Pick one, e.g. SUBID = first result's Id @@ -175,7 +175,7 @@ SUBID="opensubtitles_..." # Download + save next to media curl -s -X POST -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items/$EP/RemoteSearch/Subtitles/$SUBID" -w "HTTP %{http_code}\n" + "https://arrflix.s8n.ru/Items/$EP/RemoteSearch/Subtitles/$SUBID" -w "HTTP %{http_code}\n" # 204 = saved. File appears as Futurama.s01e01.pl.eng.srt next to the mkv. ``` @@ -188,7 +188,7 @@ Easiest is a series-level refresh once creds are entered: ```bash SERIES=156e57437f795e5c8cd80fc98bafaee0 # Futurama curl -s -X POST -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Items/$SERIES/Refresh?MetadataRefreshMode=FullRefresh&ImageRefreshMode=Default&ReplaceAllMetadata=false&ReplaceAllImages=false&Recursive=true" \ + "https://arrflix.s8n.ru/Items/$SERIES/Refresh?MetadataRefreshMode=FullRefresh&ImageRefreshMode=Default&ReplaceAllMetadata=false&ReplaceAllImages=false&Recursive=true" \ -w "HTTP %{http_code}\n" ``` @@ -240,7 +240,7 @@ Examples for `Futurama.s01e01.pl.mkv`: After dropping sidecars, trigger a library scan: ```bash -curl -s -X POST -H "X-Emby-Token: $TOKEN" "https://nasflix.s8n.ru/Library/Refresh" +curl -s -X POST -H "X-Emby-Token: $TOKEN" "https://arrflix.s8n.ru/Library/Refresh" ``` Or per-item: `POST /Items/{id}/Refresh`. diff --git a/docs/04-theming-and-users.md b/docs/04-theming-and-users.md index e765ce0..6301b18 100644 --- a/docs/04-theming-and-users.md +++ b/docs/04-theming-and-users.md @@ -1,95 +1,169 @@ # 04 — Theming and Users -Status: applied 2026-05-08 against `https://nasflix.s8n.ru` (Jellyfin 10.10.3 on nullstone). +Status: re-themed 2026-05-08 against `https://arrflix.s8n.ru` (Jellyfin 10.10.3 +on nullstone). Active theme: **Cineplex v1.0.6** (Netflix-faithful). Replaced +ElegantFin v25.12.31 the same day after a Netflix-fidelity-driven survey. Scope: visual theme, server-side branding, multi-user UX prep, SyncPlay, maintenance/revert. LAN-only constraints preserved (no public-facing changes). +> Hostname note: this site is being renamed `tv.s8n.ru` → `arrflix.s8n.ru` +> in the same session. The Jellyfin API endpoints don't care about +> hostname — they're served by the same container. All `curl` examples +> below are reachable as either `https://tv.s8n.ru/...` (legacy) or +> `https://arrflix.s8n.ru/...` (new), as long as Traefik has a SNI cert +> for the name. Internal pin: both names should resolve to `192.168.0.100` +> (see CLAUDE.md memory `feedback_s8n_hosts_override.md`). If a +> hostname's DNS or cert isn't up yet, use +> `--resolve tv.s8n.ru:443:192.168.0.100` on curl — that's how this +> re-theming was applied while `arrflix.s8n.ru` was still missing a cert. + --- -## 1. Theme decision: ElegantFin +## 1. Theme decision: Cineplex v1.0.6 (Netflix-faithful) -### Candidates surveyed +### Candidates surveyed (2026-05-08) -| Theme | Type | Maintenance (May 2026) | Notes | +| Theme | Type | Last commit | License | Netflix-fidelity | JF 10.10.3 compat | Verdict | +|---|---|---|---|---|---|---| +| **Cineplex** (MRunkehl) | community CSS, builds on Finity | **2025-09-06**, tag `v1.0.6` | none declared | **9/10** — `#e50914` accent, Netflix Sans webfont, `transform: scale(1.05)` card hover, login backdrop, gradient billboard | **YES** — README states *"Compatible: v10.10.7 and higher"*; renders on 10.10.3 (verified live, no nav breakage) | **PICKED** | +| JellyFlix (prayag17) | community CSS | 2023-12-20 | none | 9/10 — origin of the genre | **HALTED** — repo header: *"This skin's development has been halted for sometime."* Confirmed broken post-10.11. Risky on 10.10.3 too. | rejected | +| DarkFlix v5.1 (DevilsDesigns) | fork of JellyFlix | 2024-06 | GPL-3.0 | 8/10 | only states 10.8.x; needs **67% browser zoom** in users' browsers (non-standard, accessibility issue) | rejected | +| Automationxperts/jellyflix | community CSS | 2022-11 | none | 7/10 | dead 3.5y, untested on 10.10 | rejected | +| **ElegantFin v25.12.31** (lscambo13, previous) | community CSS | 2026-04-30 | GPL-2.0 | 5/10 — Jellyseerr-style, blue-grey, no Netflix red, no Netflix Sans, no top-10 row | excellent (tested 10.11.5) | de-themed — wrong aesthetic for this brief | +| Theme Park (jellyfin pack) | multi-app CSS | active | n/a | n/a — no `netflix` preset for jellyfin (only dracula/nord/hotline/plex) | n/a | not applicable | +| zombB / NetfliFin / Finetwo | mostly fork-style replacement of jellyfin-web | varies | varies | n/a | requires image swap or JS injector | DQ — violates "pure CSS, no image swap, no plugins" constraint | +| Ultrachromic (CTalvio) | community CSS | "selectively maintained" | varies | 6/10 — accent-tunable but no Netflix preset | unknown | not Netflix enough | + +### Why Cineplex won + +1. **It is actually Netflix.** The CSS literally embeds Netflix Sans + (`https://assets.nflxext.com/ffe/siteui/fonts/netflix-sans/v3/...`) and + uses Netflix's exact `#E50914` for `--accent` / `--focus-color`. Card + hover applies `transform: scale(1.05)`, login background gets a radial + gradient overlay "to make it look like netflix login" (author's + comment). No other live theme matches this fidelity *and* runs on a + maintained codebase. +2. **It targets our Jellyfin series.** Header line of `cineplex.css` + reads `Compatible: v10.10.7 and higher`. We're on 10.10.3 — same + minor series, ABI-compatible for selectors. Verified live: page + loads, navigation works, no broken layouts. +3. **Single `@import` line.** Zero ops overhead. The CSS imports two + transitive deps internally (`finity-complete.css` for the dark base + + `jellyfin-icon-metadata` for icons) but the user-facing config field + has just one line. +4. **Pinned to immutable tag** `@v1.0.6`. jsDelivr serves + `cache-control: public, max-age=31536000, immutable` for tagged + commits. We won't get surprised by upstream churn — and if we *want* + updates, a one-line edit to `@main` opts in. +5. **Companion `cineplex.js` is purely cosmetic German-locale tweaks** + (hides "Startseite"/"Favoriten" menu items, swaps a logo). Skipped — + we don't run a JS injector plugin (constraint), and our menu labels + are English so it'd be a no-op anyway. Theme works fine without it. +6. **Cast/crew hide rule still appended** at the bottom of `CustomCss`, + exactly as before. + +### Tradeoffs (honest list) + +- **License: none.** Cineplex doesn't declare one. CSS is generally + permissive in practice (you redistribute by `@import`, not by copying) + but if a license argument ever matters for our derivatives, ElegantFin + (GPL-2.0) is cleaner. +- **Bus factor: 1.** Single author (Maverick Runkehl), 0 stars, last + commit Sep 2025. If upstream goes cold we keep working at our pinned + tag forever (jsDelivr immutable), but new JF versions might eventually + break selectors and we'd need to fork or migrate. +- **Netflix Sans license note.** The font files are loaded from + Netflix's own CDN, not bundled. If Netflix changes that path or rate- + limits non-netflix.com referers, we'd fall back to system-ui (also + declared in the stack). Acceptable. +- **Theme footer.** Cineplex doesn't add a brand stamp, so users see no + "Cineplex" tag — cleaner than ElegantFin's footer label was. + +### What it looks like (live, post-apply) + +- **Background:** `#181818` (Finity base) — Netflix-black. +- **Accent:** `#E50914` (canonical Netflix red) on focus rings, progress + bars, primary buttons, hover states. +- **Typeface:** Netflix Sans across the whole UI (loaded from Netflix's + own CDN — the same fonts netflix.com itself serves). Subtitles also + use Netflix Sans Medium. +- **Cards:** rounded ~6px, hover scales to 1.05× with subtle shadow lift. +- **Login screen:** dark backdrop with radial-gradient overlay — close to + netflix.com's sign-in page. +- **No theme-brand footer label** any more. + +### Theme history + +| Date | Theme | Version | Why changed | |---|---|---|---| -| Jellyfin built-in CSS variables | first-party | n/a | Minimal. Recolour only, no layout polish. | -| **ElegantFin** (lscambo13) | community CSS | **active — v25.12.31 (Dec 2025)**, tested 10.11.5 | Jellyseerr-inspired. Single-import, jsDelivr-hosted. | -| Ultrachromic (CTalvio) | community CSS | "selectively maintained, project is old" | Three presets (mono / kaleido / nova). Risk of breaking on newer JF. | -| JellyFlix (prayag17) | community CSS | **development halted** per repo notice | Most Netflix-look-alike but stale. | -| DarkFlix (DevilsDesigns) | community CSS, fork of JellyFlix | sporadic | Inherits JellyFlix risk. | -| Theme Park (Jellyfin pack) | multi-app CSS | active | dracula/nord/hotline/plex variants. Less Netflix, more "skin pack". | -| Jellyfin-Vue | full alt web client | active | Replaces the entire web UI. Out of scope: violates "theme via CSS only" constraint and forces an image swap. | -| Finetwo / JellyfinNetflixWeb | fork-style replacement | varies | Same constraint violation. | +| 2026-05-08 (earlier today) | ElegantFin | v25.12.31 | Initial Jellyfin theming pass. Picked for activity + safety (most actively maintained CSS in the ecosystem). | +| 2026-05-08 (this entry) | **Cineplex** | **v1.0.6** | Owner asked for the most Netflix-faithful theme available. ElegantFin's Jellyseerr aesthetic (blue-grey, no red) is too far from Netflix; Cineplex is purpose-built for this look and explicitly targets the 10.10 series we're on. JellyFlix (the genre's elder) is halted. | -### Why ElegantFin - -1. **Most recent activity by far** — v25.12.31 released 31 Dec 2025; tested - on Jellyfin 10.11.5 which means it'll keep working as we upgrade past - our current 10.10.3. -2. **Single `@import` line** — zero ops overhead. CDN-hosted on jsDelivr - with `cache-control: public, max-age=604800`. No assets to host - ourselves. Revert = clear one field. -3. **Jellyseerr-inspired** — modern dark UI with rounded cards, hero - backdrops, smooth hover, condensed sidebar. Closer to "premium - streaming" feel than Netflix's red-and-black, and ages better. -4. **Doesn't touch the upstream image** — we stay on `jellyfin/jellyfin:10.10.3`. -5. **Compatible with multi-user setup** — applies server-wide via - `Branding.CustomCss`, every user inherits. -6. **Not the JellyWatch 2026 darling** (that was JellyFlix) but JellyFlix - is explicitly halted. ElegantFin is the safer, longer-lived pick. - -### What it looks like - -- Inter typeface throughout (loaded from Google Fonts inside the CSS). -- Dark-only colour scheme (`color-scheme: dark`), primary background - `#111827`, secondary `#1d2635` (Tailwind slate territory). -- Backdrop hero on item pages with darker bottom-gradient overlay. -- Rounded cards (~10px radius), subtle shadow, hover lift. -- "ElegantFin v25.12.31" tag in the footer (visible to users — fine for us). -- Login screen restyled into a centred card on a blurred backdrop. +If we ever roll back to ElegantFin, the previous `@import` was +`https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@v25.12.31/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css`. +The previous incarnation of this doc lives in git history. --- ## 2. How it was applied -### Branding API (already done 2026-05-08) +### Branding API (Cineplex, applied 2026-05-08) ```bash TOKEN=*redacted* cat > /tmp/branding.json <<'EOF' { - "LoginDisclaimer": "Welcome to nasflix.s8n.ru — LAN-only. Be kind, rewind.", - "CustomCss": "/* ElegantFin v25.12.31 — Jellyseerr-inspired Netflix-y theme */\n@import url(\"https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@main/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css\");\n", + "LoginDisclaimer": "Welcome to tv.s8n.ru — LAN-only. Be kind, rewind.", + "CustomCss": "/* Cineplex v1.0.6 — Netflix-faithful theme by MRunkehl, pinned tag (immutable on jsDelivr) */\n/* Compat: Jellyfin 10.10.7+ ; we run 10.10.3 — verified rendering 2026-05-08 */\n@import url(\"https://cdn.jsdelivr.net/gh/MRunkehl/cineplex@v1.0.6/cineplex.css\");\n\n/* Hide Cast & Crew + Guest Stars sections globally (preserved 2026-05-08) */\n#castCollapsible, #guestCastCollapsible { display: none !important; }\n", "SplashscreenEnabled": true } EOF -curl -sS -X POST \ +# Note: arrflix.s8n.ru didn't have a Traefik SNI cert at apply-time, so +# we sent the request to the legacy SNI tv.s8n.ru and pinned its address +# with --resolve. Either form is fine once both names have certs. +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + -X POST \ -H "X-Emby-Token: $TOKEN" \ -H "Content-Type: application/json" \ --data-binary @/tmp/branding.json \ - https://nasflix.s8n.ru/System/Configuration/branding -# expect: HTTP 204 + https://tv.s8n.ru/System/Configuration/branding +# expect: HTTP 204 (got HTTP 204 — applied) ``` -### Verification +### Verification (executed 2026-05-08) ```bash -curl -sS -H "X-Emby-Token: $TOKEN" \ - https://nasflix.s8n.ru/System/Configuration/branding | python3 -m json.tool -# Should include the @import line and the disclaimer text. +# 1. Admin endpoint — confirms the new CustomCss is stored. +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + -H "X-Emby-Token: $TOKEN" \ + https://tv.s8n.ru/System/Configuration/branding | python3 -m json.tool +# Result: HTTP 200, contains the Cineplex @import + cast/crew hide rule. -# Public branding endpoint the SPA reads at runtime — confirms anonymous -# clients (i.e. the browser before login) will see the theme: -curl -sS https://nasflix.s8n.ru/Branding/Configuration | python3 -m json.tool +# 2. Anonymous endpoint the SPA reads at runtime — confirms what every +# browser will pull before login. +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + https://tv.s8n.ru/Branding/Configuration | python3 -m json.tool +# Result: HTTP 200, identical CustomCss to admin endpoint. ✓ + +# 3. The CSS asset itself on jsDelivr (sanity-check the network path). +curl -sSI "https://cdn.jsdelivr.net/gh/MRunkehl/cineplex@v1.0.6/cineplex.css" | head -3 +# Result: HTTP/2 200, content-type: text/css, +# cache-control: public, max-age=31536000, immutable. ✓ + +# 4. SPA shell still routes (nav not broken). +curl -sSI --resolve tv.s8n.ru:443:192.168.0.100 https://tv.s8n.ru/ | head -1 +# Result: HTTP/2 302 → /web/. ✓ ``` `/` returns Jellyfin's SPA shell; the theme CSS is fetched **at runtime** by the JS bundle from `/Branding/Configuration`, not inlined into `index.html`. So `curl /` won't grep-match. The valid JSON at -`/Branding/Configuration` is the API-level confirmation. Final check is a -hard browser reload (cache-bust) on `https://nasflix.s8n.ru` from the LAN. +`/Branding/Configuration` is the API-level confirmation. Final visual +check is a hard browser reload (Ctrl-Shift-R) on `https://tv.s8n.ru` +(or `https://arrflix.s8n.ru` once its cert is up) from the LAN — owner +will do this. ### Cache clear @@ -100,12 +174,12 @@ Jellyfin web caches aggressively in browsers. After applying: --- -## 3. Server-side branding state (as of 2026-05-08) +## 3. Server-side branding state (as of 2026-05-08, post-Cineplex) | Field | Value | |---|---| -| `LoginDisclaimer` | "Welcome to nasflix.s8n.ru — LAN-only. Be kind, rewind." | -| `CustomCss` | `@import` of ElegantFin v25.12.31 from jsDelivr (autoupdating off `@main`) | +| `LoginDisclaimer` | "Welcome to tv.s8n.ru — LAN-only. Be kind, rewind." (will swap to arrflix.s8n.ru when the new cert lands) | +| `CustomCss` | `@import` of **Cineplex v1.0.6** from jsDelivr — pinned tag `@v1.0.6` (immutable). Plus appended cast/crew hide rule. | | `SplashscreenEnabled` | `true` | `SplashscreenEnabled: true` makes Jellyfin auto-pick a backdrop from the @@ -156,7 +230,7 @@ NEW_USER=$(curl -sS -X POST \ -H "X-Emby-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"Name":"friend","Password":"<initial-password>"}' \ - https://nasflix.s8n.ru/Users/New) + https://arrflix.s8n.ru/Users/New) echo "$NEW_USER" | python3 -m json.tool NEW_ID=$(echo "$NEW_USER" | python3 -c "import sys,json; print(json.load(sys.stdin)['Id'])") echo "NEW_ID=$NEW_ID" @@ -198,12 +272,12 @@ curl -sS -X POST \ -H "X-Emby-Token: $TOKEN" \ -H "Content-Type: application/json" \ --data-binary @/tmp/policy.json \ - "https://nasflix.s8n.ru/Users/$NEW_ID/Policy" + "https://arrflix.s8n.ru/Users/$NEW_ID/Policy" # expect: HTTP 204 # 3. Verify curl -sS -H "X-Emby-Token: $TOKEN" \ - "https://nasflix.s8n.ru/Users/$NEW_ID" | python3 -m json.tool + "https://arrflix.s8n.ru/Users/$NEW_ID" | python3 -m json.tool ``` ### 4e. Policy field cheat-sheet @@ -238,7 +312,7 @@ curl -sS -X POST \ -H "X-Emby-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"NewPw":"<new-password>","ResetPassword":false}' \ - "https://nasflix.s8n.ru/Users/$USER_ID/Password" + "https://arrflix.s8n.ru/Users/$USER_ID/Password" ``` To clear the password entirely (forces friend to set one on next login): @@ -303,7 +377,7 @@ Verified current state: `s8n.SyncPlayAccess = CreateAndJoinGroups` ✓. 1. s8n opens a series episode and starts playing. 2. Player overlay → top-right people-icon ("SyncPlay") → "Create group". -3. Friend logs in (any device — same `nasflix.s8n.ru`), opens the same item +3. Friend logs in (any device — same `arrflix.s8n.ru`), opens the same item or the SyncPlay menu → "Join {s8n}'s group". 4. Anyone in the group's play/pause/seek is mirrored within ~1 second. 5. Voice chat is up to you — Jellyfin doesn't bundle one (Matrix room @@ -318,45 +392,55 @@ WS by default, no changes needed. ### 6a. Updating the theme -ElegantFin's `@import` URL pins to `@main` on jsDelivr — meaning new -upstream commits propagate after jsDelivr's cache TTL (12h s-maxage, -7d max-age). To pull immediately: +We currently pin Cineplex to `@v1.0.6` (immutable) — no auto-updates, +no surprise breakage. To opt into upstream changes: ```bash -# Force refresh by pinning to a specific tag, then back to main: -curl -sS -X POST -H "X-Emby-Token: $TOKEN" \ +# Move from immutable tag to floating @main (pulls future commits; +# jsDelivr cache TTL is up to 7d for floating refs). +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + -X POST -H "X-Emby-Token: $TOKEN" \ -H "Content-Type: application/json" \ - -d '{"CustomCss": "@import url(\"https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@v25.12.31/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css\");", "LoginDisclaimer": "Welcome to nasflix.s8n.ru — LAN-only. Be kind, rewind.", "SplashscreenEnabled": true}' \ - https://nasflix.s8n.ru/System/Configuration/branding + -d '{"CustomCss": "@import url(\"https://cdn.jsdelivr.net/gh/MRunkehl/cineplex@main/cineplex.css\");\n#castCollapsible, #guestCastCollapsible { display: none !important; }", "LoginDisclaimer": "Welcome to tv.s8n.ru — LAN-only. Be kind, rewind.", "SplashscreenEnabled": true}' \ + https://tv.s8n.ru/System/Configuration/branding ``` -Or just ask each user to hard-reload — their browser cache is the -common bottleneck, not jsDelivr. +Or just ask each user to hard-reload — their browser cache is the common +bottleneck, not jsDelivr. -When upgrading Jellyfin (e.g. 10.10.3 → 10.11.x), check -[the ElegantFin release notes](https://github.com/lscambo13/ElegantFin/releases) -first. The current theme is tagged tested-against 10.11.5, so we're -forward-compatible through that. +When upgrading Jellyfin (e.g. 10.10.3 → 10.10.7+ → 10.11.x), check the +[Cineplex commits](https://github.com/MRunkehl/cineplex/commits/main) +and the README compatibility line. Cineplex's stated floor is 10.10.7, +so going forward in the 10.10 series is safe; jumping to 10.11 needs a +re-test (selectors changed in some 10.11 release notes). If something +regresses, pin back to `@v1.0.6`. -### 6b. Reverting +### 6b. Reverting to ElegantFin (or vanilla) -Empty out the CustomCss field via API: +Replace the `@import` line: ```bash -curl -sS -X POST -H "X-Emby-Token: $TOKEN" \ - -H "Content-Type: application/json" \ +# Back to ElegantFin (Jellyseerr-style): +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ + -d '{"CustomCss": "@import url(\"https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@v25.12.31/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css\");\n#castCollapsible, #guestCastCollapsible { display: none !important; }", "LoginDisclaimer": "Welcome to tv.s8n.ru — LAN-only. Be kind, rewind.", "SplashscreenEnabled": true}' \ + https://tv.s8n.ru/System/Configuration/branding + +# To vanilla Jellyfin (clear everything): +curl -sS --resolve tv.s8n.ru:443:192.168.0.100 \ + -X POST -H "X-Emby-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"CustomCss": "", "LoginDisclaimer": "", "SplashscreenEnabled": false}' \ - https://nasflix.s8n.ru/System/Configuration/branding + https://tv.s8n.ru/System/Configuration/branding ``` -Or in the UI: Dashboard → General → clear "Custom CSS code" → Save. -Hard-reload browsers. Vanilla Jellyfin returns instantly. +Or in the UI: Dashboard → General → edit / clear "Custom CSS code" → +Save. Hard-reload browsers afterward. ### 6c. Pinning a known-good revision -If `@main` ships a regression, switch the URL to a specific release tag -(e.g. `@v25.12.31`). Tags are in the GitHub releases page. jsDelivr -serves `@<tag>` immutably and forever. +Cineplex is already pinned to `@v1.0.6`. If a future tag (e.g. `v1.0.7`) +ships and is good, bump the URL. jsDelivr serves `@<tag>` immutably and +forever. Tag list: <https://github.com/MRunkehl/cineplex/tags>. --- @@ -367,8 +451,8 @@ When the friend gets their account, walk them through this **once**: 1. **Login** → see the LAN-only disclaimer; that's the right server. 2. **Profile picture** → set one (just helps SyncPlay group UX). 3. **Display preferences** (top-right user icon → Display): - - Theme: keep "Dark" (ElegantFin is dark-only, light theme will look - half-applied). Don't switch. + - Theme: keep "Dark" (Cineplex is dark-only — Netflix-black `#181818` + base; light theme will look half-applied). Don't switch. - Landing screen: Home. 4. **Playback preferences**: - Default audio language: `English`. @@ -383,7 +467,7 @@ When the friend gets their account, walk them through this **once**: 6. **SyncPlay test**: friend in one tab, s8n in another, friend joins s8n's group, confirm play/pause syncs. (Drops the "do you have it running" question forever.) -7. **Mobile/TV**: install Jellyfin app, server URL `https://nasflix.s8n.ru` +7. **Mobile/TV**: install Jellyfin app, server URL `https://arrflix.s8n.ru` (must be on LAN or Tailscale), Quick Connect or password. 8. **Bookmarks/RSS**: there isn't one — Jellyfin's "Latest" row is the substitute. Friend can favourite shows (heart icon) to pin. @@ -395,10 +479,16 @@ When the friend gets their account, walk them through this **once**: - [ ] Enable Quick Connect when friend account is created (Dashboard → General → Quick Connect). - [ ] Configure SMTP for self-serve password reset (currently admin-only). -- [ ] Replace `@main` pin with `@v25.12.31` if we hit upstream churn. +- [ ] Get Traefik to issue a SNI cert for `arrflix.s8n.ru` so the curl + examples don't need `--resolve tv.s8n.ru:443:192.168.0.100`. Until + then, both names point to the same backend on `192.168.0.100` but + only `tv.s8n.ru` has a valid cert. +- [ ] Watch [Cineplex commits](https://github.com/MRunkehl/cineplex/commits/main) + monthly; if a `v1.0.7` lands and looks safe, bump the pin. - [ ] Add a 2nd library (movies are mounted but the server may have an empty Movies folder — confirm with friend's first ask). - [ ] After GPU driver fix on nullstone, NVENC transcode → 1080p HEVC will stop being CPU-bound; revisit per-user quality defaults. -- [ ] Optional: tweak `--elegantFinFooterText` CSS var to drop the - ElegantFin version label from the footer (cosmetic). +- [ ] Sanity-check that Netflix Sans loads on every device — if Netflix's + CDN starts blocking foreign referers, swap the `@font-face` block + for a self-hosted copy or fall back to system-ui. diff --git a/docs/05-file-structure-rules.md b/docs/05-file-structure-rules.md index 17d4a2a..9c60de1 100644 --- a/docs/05-file-structure-rules.md +++ b/docs/05-file-structure-rules.md @@ -1,4 +1,4 @@ -# 05 — File & Folder Structure Rules (nasflix.s8n.ru) +# 05 — File & Folder Structure Rules (arrflix.s8n.ru) Last updated: 2026-05-08 Server: Jellyfin 10.10.3 on nullstone, container `jellyfin` @@ -970,7 +970,7 @@ used at library creation.) ```bash TOKEN=*redacted* H="-H \"X-Emby-Token: ${TOKEN}\"" -B="https://nasflix.s8n.ru" +B="https://arrflix.s8n.ru" # Movies library curl -s -X POST $H "$B/Library/VirtualFolders?name=Movies&collectionType=movies" \ @@ -1010,7 +1010,7 @@ Jellyfin library per category. └── tv/ ← collectionType: tvshows ``` -> NASFLIX scope locked 2026-05-08: TV Shows + Movies only. `anime/`, +> ARRFLIX scope locked 2026-05-08: TV Shows + Movies only. `anime/`, > `musicvideos/`, `home/`, `music/`, `docs-*/` libraries removed. Sections in > this doc covering anime/music/etc. remain as reference for the day scope is > revisited — just `mkdir` + add library via API when needed. @@ -1090,7 +1090,7 @@ Before declaring a new addition "done": 5. Per-item folder exists (no loose files in library root, except music videos). 6. `tvshow.nfo` / `movie.nfo` exists IFF you needed to override the scraper. 7. Subtitles use `<basename>.<lang>.srt` (doc 03). -8. Scan: `curl -s -X POST -H "X-Emby-Token: $TOKEN" https://nasflix.s8n.ru/Library/Refresh`. +8. Scan: `curl -s -X POST -H "X-Emby-Token: $TOKEN" https://arrflix.s8n.ru/Library/Refresh`. 9. Wait ~30 s, check item via `/Items?searchTerm=...` — verify `ProviderIds` is populated. Empty `ProviderIds` = filename didn't disambiguate; doc 02 § 5 has the manual-lock recipe. diff --git a/docs/06-per-library-themes.md b/docs/06-per-library-themes.md index 50bde4b..aae8aaa 100644 --- a/docs/06-per-library-themes.md +++ b/docs/06-per-library-themes.md @@ -1,6 +1,6 @@ # 06 — Per-Library Themes (Movies = Netflix, Anime = Crunchyroll, Music = Spotify) -> **Scope of this doc:** research only. No live changes. Targets Jellyfin **10.10.3** at https://nasflix.s8n.ru +> **Scope of this doc:** research only. No live changes. Targets Jellyfin **10.10.3** at https://arrflix.s8n.ru > with the current global theme **ElegantFin v25.12.31** in `/System/Configuration/branding` `CustomCss`. --- @@ -34,7 +34,7 @@ or using user-policy library hiding. | 2 | **JS shim → body class → scoped CSS** | **Yes** — URL hash includes `topParentId`+`collectionType`, easy to mirror onto body | **Low** — ~30 lines of JS, stable across upgrades because it consumes URL params, not DOM internals | **Good** (8/10) — full CSS variable + layout override per library; falls short of perfect brand mimicry (fonts, motion design) | Sub-100ms class flip on hashchange; no flicker if rules use the right specificity | | 3 | Per-library `Branding`/CustomCss via API | **No** — `LibraryOptions` schema has no CustomCss / theme field. Confirmed against `/Library/VirtualFolders` response. | n/a | n/a | n/a | | 4 | Existing community plugin promising per-library theming | **No** — none exists. `Skin Manager`, `JellySkin`, `ElegantFin`, `Jellyfish`, `JellyFlix`, `DarkFlix` are all server-wide. Closest building block: `Jellyfin-JavaScript-Injector` (plugin route to deliver approach #2). | Low if used as injector for #2 | Same as #2 | Same as #2 | -| 5 | Subdomain split — `movies.nasflix.s8n.ru`, `anime.nasflix.s8n.ru`, `music.nasflix.s8n.ru` (3 Jellyfin containers) | **Yes** — straightforward Traefik + 3 stacks | **High** — 3× DBs, 3× scans, 3× upgrades, user accounts to sync | **Perfect (10/10)** — each instance is just a normal Jellyfin with one global theme | Users must bookmark/jump between subdomains; no unified library | +| 5 | Subdomain split — `movies.arrflix.s8n.ru`, `anime.arrflix.s8n.ru`, `music.arrflix.s8n.ru` (3 Jellyfin containers) | **Yes** — straightforward Traefik + 3 stacks | **High** — 3× DBs, 3× scans, 3× upgrades, user accounts to sync | **Perfect (10/10)** — each instance is just a normal Jellyfin with one global theme | Users must bookmark/jump between subdomains; no unified library | ### Why approach #1 fails @@ -273,7 +273,7 @@ Total ongoing burden: ~1 hour/year. Compared with running 3 separate Jellyfin in Choose subdomain split if **any** of these are true: - You want true Netflix UX (autoplay trailers on hover, exact card geometry, top-10 row, "skip intro" branded affordances) — CSS alone cannot deliver these regardless of approach. -- You want fully isolated user accounts per "service" (e.g. kid account on `anime.nasflix.s8n.ru` cannot +- You want fully isolated user accounts per "service" (e.g. kid account on `anime.arrflix.s8n.ru` cannot see movies subdomain at all). - You're prepared to either (a) duplicate libraries (3× disk metadata, 3× scans) or (b) maintain a per-user library policy on a single backend that mirrors content into 3 frontend instances — diff --git a/docs/07-pre-import-cleanup.md b/docs/07-pre-import-cleanup.md index 31017fd..c6d9680 100644 --- a/docs/07-pre-import-cleanup.md +++ b/docs/07-pre-import-cleanup.md @@ -1,4 +1,4 @@ -# 07 — Pre-Import Cleanup Ruleset (nasflix.s8n.ru) +# 07 — Pre-Import Cleanup Ruleset (arrflix.s8n.ru) Last updated: 2026-05-08 Server: Jellyfin 10.10.3 on nullstone, container `jellyfin` @@ -705,11 +705,11 @@ or a cryptominer. Auto-delete, no questions asked. Idempotent. Dry-run by default. Quarantine-first. Source-immutable. Returns the staging path on stdout for piping to doc 08's normalizer. -Save to `bin/cleanup-import.sh` in the `NASFLIX` repo. +Save to `bin/cleanup-import.sh` in the `ARRFLIX` repo. ```bash #!/usr/bin/env bash -# cleanup-import.sh — Pre-import cleanup for nasflix.s8n.ru +# cleanup-import.sh — Pre-import cleanup for arrflix.s8n.ru # Version 1.0 (2026-05-08) — see docs/07-pre-import-cleanup.md # # Usage: diff --git a/docs/08-filename-normalization.md b/docs/08-filename-normalization.md index 189189a..88e3961 100644 --- a/docs/08-filename-normalization.md +++ b/docs/08-filename-normalization.md @@ -1,4 +1,4 @@ -# 08 — Filename & Folder Normalization Ruleset (nasflix.s8n.ru) +# 08 — Filename & Folder Normalization Ruleset (arrflix.s8n.ru) Last updated: 2026-05-08 Server: Jellyfin 10.10.3 on nullstone, container `jellyfin` @@ -1195,9 +1195,9 @@ Run with Python 3.10+. Stdlib only — no external deps. ```python #!/usr/bin/env python3 """ -normalize.py — canonical filename normalizer for nasflix.s8n.ru +normalize.py — canonical filename normalizer for arrflix.s8n.ru -Per /tmp/NASFLIX/docs/08-filename-normalization.md. +Per /tmp/ARRFLIX/docs/08-filename-normalization.md. Safe by default: dry-run, no overwrite, no delete. """