Rename: nasflix → ARRFLIX + apply Cineplex theme
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).
This commit is contained in:
parent
cb95dce8bc
commit
1f5ba31483
14 changed files with 234 additions and 144 deletions
|
|
@ -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-<title>/<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.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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}`).
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
BIN
assets/logo.png
Normal file
BIN
assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.3 KiB |
|
|
@ -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>}"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 —
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
"""
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue