feat(jellyfin): big-screen theme for the TV, mounted into the wmc slot

This commit is contained in:
Frank committed 2026-11-03 03:38:15 -08:00
1 parent 64f489023e
commit 51abc6550d
3 files changed
+94

No files matched your search

@@ -47,6 +47,12 @@ Volume=/home/dank/Containers/jellyfin/cache:/cache
# is the guard: started against a plain, unmounted view directory a scan decides # is the guard: started against a plain, unmounted view directory a scan decides
# the library is empty and deletes what it cannot see. # the library is empty and deletes what it cannot see.
Volume=/var/lib/media-meta/view:/data Volume=/var/lib/media-meta/view:/data
# Big-screen theme for the TV. The repo file replaces the container's "Media
# Center" theme slot; the upstream dark palette stays live because the file
# @imports it, so an image bump cannot strand a vendored CSS snapshot. Read-only
# — the web app only fetches it. A client opts in with
# Display Settings -> Theme -> "Media Center".
Volume=/home/dank/serverAppConfigs/dankserver/jellyfin/theme/wmc/theme.css:/jellyfin/jellyfin-web/themes/wmc/theme.css:ro
AddDevice=/dev/dri AddDevice=/dev/dri
GroupAdd=keep-groups GroupAdd=keep-groups
HealthCmd=curl -f http://localhost:8096/health HealthCmd=curl -f http://localhost:8096/health
+53
View File
@@ -0,0 +1,53 @@
/*
* Dank fleet big-screen theme for jellyfin-web.
*
* Deployed by bind-mounting THIS file over the container's "Media Center"
* theme (`/jellyfin/jellyfin-web/themes/wmc/theme.css`) — see the Volume line
* in dankserver/jellyfin/quadlet/jellyfin.container. The slot is deliberately
* one nobody picks by accident, and its name is the only thing that changes:
* the colors are the live upstream dark theme, pulled in by @import below, so
* this file never vendors a snapshot of upstream CSS and cannot drift when the
* Jellyfin image moves.
*
* Why it exists: the living-room client (Jellyfin Desktop on danklivingroom)
* renders this server-served web app at 3840x2160 with no client-side scaling,
* so 14 px body text lands on a big panel viewed from three metres. `zoom` on
* the root element is the one lever that scales the whole UI — the layout code
* measures layout px, so card grids re-flow to fewer, larger columns instead of
* overflowing.
*
* Adoption is per device, not global: Display Settings -> Theme ->
* "Media Center" on the screen that wants it. That is the point — a phone
* browser on the same server must not get a 1.75x interface.
*
* Change the size by editing the single number. 1.5 is mild, 1.75 is the
* three-metre default, 2.0 is for a projector.
*/
@import url("../dark/theme.css");
:root {
/* Marker the e2e gate reads back; also a tweak hook for a per-client
override injected by anyone who really wants one. */
--dank-big-screen: 1;
--dank-big-screen-zoom: 1.75;
}
html {
zoom: var(--dank-big-screen-zoom);
}
/* A remote moves focus in discrete jumps, so the ring has to survive a
three-metre read. */
.emby-focus,
button:focus-visible,
a:focus-visible,
.inputElement:focus-visible {
outline: 3px solid var(--accentColor, #00a4dc) !important;
outline-offset: 2px !important;
}
/* Scrollbars are mouse furniture; on a TV they are noise at this size. */
* {
scrollbar-width: none;
}
@@ -407,6 +407,41 @@ removed. Discover a route's verb from the `Allow` header of an `OPTIONS` (or
Seerr keeps a key of its own in its own DB (which of its two rows it uses was Seerr keeps a key of its own in its own DB (which of its two rows it uses was
never confirmed), so revoke by token and never by app name. never confirmed), so revoke by token and never by app name.
## Big-screen theme (the TV)
`dankserver/jellyfin/theme/wmc/theme.css` is repo-owned and bind-mounted over the
image's **Media Center** theme slot (the `Volume=` line in
`dankserver/jellyfin/quadlet/jellyfin.container`). It exists for
`danklivingroom`, which renders this server-served web app at 3840×2160 with no
client-side scaling, so 14 px text arrives on a panel read from three metres.
The file is four rules, and its first line is the design:
`@import url("../dark/theme.css")` pulls in the **live upstream** dark palette, so
the repo never vendors a CSS snapshot and a Jellyfin image bump cannot strand one.
That works because jellyfin-web applies a theme as
`<link rel="stylesheet" href="themes/<id>/theme.css">` — a relative URL resolved
against the CSS file, not the document. The size lives in one number:
`--dank-big-screen-zoom` (1.75 ≈ three metres; 1.5 mild, 2.0 projector). `zoom` on
the root element is the right lever: the card-grid code measures layout pixels, so
fewer, larger columns are computed rather than overflow produced.
- **Adoption is per device, and it stays that way.** The theme a client renders
comes from its own settings (localStorage first), so there is no server-side
"everyone gets the big UI" knob. On the screen that wants it:
**Display Settings → Theme → Media Center.** That is also the honest label —
the dropdown names are compiled into the bundle, so a "Big Screen" entry will
never appear; do not go looking for one.
- The mount is `:ro` and the app only fetches the file, so the failure mode of a
stale `@import` target is slightly wrong colors, never a dead web app.
- **Editing the CSS needs no restart.** The bind hands out the host file's live
bytes, so a changed zoom number is on screen at the next page load. The planner
agrees by construction: only `dankserver/<svc>/quadlet/**` maps to a service, so
a `theme/**`-only commit plans nothing — that is correct, not a gap to "fix",
because restarting a media server for a font size is the wrong trade. Only the
first deploy of the `Volume=` line restarts anything.
- **Rollback is one line:** drop the `Volume=` and redeploy; nothing in the
database records the theme, so no cleanup follows.
## See Also ## See Also
- [[Plex]] — co-resident media server on the same volume - [[Plex]] — co-resident media server on the same volume