//nbkelley /homelab

Jellyfin Help Link Integration

Jellyfin Help Link Integration#

What Was Established#

  • Goal: Integrate a persistent, user-facing help link directly into the Jellyfin UI for logged-in users, directing them to the Hinterflix documentation.
  • Methods Evaluated: Custom Login Message (pre-login only), Custom CSS (Dashboard > General), Reverse Proxy HTML injection (Nginx), Custom JavaScript, and Plugin-based solutions.
  • Selected Approach: Custom CSS injected via the Jellyfin Dashboard. It provides immediate visibility without requiring external dependencies or server restarts.

Key Decisions#

  • Placement: Prioritized persistent in-interface links over pre-login messages. Options included header navigation, floating action button, and sidebar integration.
  • Implementation Path: Chose Dashboard > General > Custom CSS for its simplicity and zero-dependency nature compared to reverse proxy modifications or plugin development.
  • Target URL: The CSS href attributes should point to the deployed Hinterflix help site (e.g., https://status.nbkelley.com or the specific docs subdomain).

Current Configuration#

  • Location: Jellyfin Web UI → Dashboard → General → Custom CSS
  • Active Selectors:
    • headerTabs::after for top navigation bar integration
    • body::after for a fixed floating action button (FAB)
    • sidebarBox:last-child::after for sidebar menu integration
  • Dependencies: None. Relies entirely on Jellyfin’s built-in CSS injection capability.

Historical Notes#

  • Conversation dated 2025-11-22.
  • Jellyfin’s frontend framework (Ember.js/React hybrid) frequently updates CSS class names. Selectors like headerTabs and sidebarBox may break after major Jellyfin version upgrades, requiring CSS updates.
  • The sub_filter Nginx approach was considered but discarded in favor of native dashboard configuration to avoid proxy overhead and cache invalidation issues.

Open Questions#

  • Has the chosen CSS snippet been applied and verified against the current Jellyfin version running on the homelab?
  • Are there any specific UX guidelines or family-user constraints that dictate the preferred placement (header vs. floating vs. sidebar)?

Sources#

  • ingested/chats/128-Add User to Sudoers Group Guide.md
  • ingested/chats/113-Adding Help Link to Jellyfin Server.md
  • ingested/chats/028-Basic Header with Hamburger Menu Design.md
  • DeepSeek conversation: “Adding Help Link to Jellyfin Server” (2025-11-22)

MBTA Dashboard - Frontend Implementation

MBTA Dashboard - Frontend Implementation#

What Was Established#

A portrait-mode (1080x1920) transit dashboard displaying real-time MBTA departures, commuter rail, weather, news, and a static transit map. Hosted on PLT-MBTADisplay (192.168.168.42), served via Nginx with a Node/Express proxy that handles all external API calls server-side. Target display is a 1080p vertical screen driven by Anthias on a Raspberry Pi 3B+.

Design Evolution#

The dashboard went through several major design iterations:

  1. Initial: Line-based cards with MBTA colors, horizontal layout for 1080p TV
  2. Minimalist redesign: White background, grey dividers, MBTA colors only on small abbreviated line pills (RL, OL, BL, GL-B/C/D/E), smaller station-only headers with walk time
  3. Station-based cards: Cards grouped by station (South Station, State Street, Park Street) rather than by line, with all routes listed per station
  4. Final portrait layout: 2-column CSS Grid, flex column containers, flat time-sorted departure list with line pills, full-width static map image at bottom

Layout (1080x1920 Portrait)#

  • 2-column, 3-row card grid above a full-width static map image
  • Cards flex with content height (no preset card height)
  • CSS Grid with grid-template-columns: 1fr 1fr

Key Features#

CSS Ticker/Marquee#

  • Header text that overflows its container scrolls seamlessly in a ticker
  • Uses CSS animation with transform: translateX() — no JavaScript
  • Animation speed set slow for readability

Station-Based Grouping#

  • Cards grouped by physical station: South Station, State Street, Park Street
  • Each station card shows all lines serving that station
  • Departures sorted by time, each with abbreviated line pill (RL, OL, BL, GL-B, etc.)
  • Filtered to show departures within 10 minutes walking distance

Server-Side Proxy Architecture#

  • All API calls proxied through Node/Express on localhost:3000
  • Client fetches single /api/data endpoint — no direct browser-to-MBTA calls
  • API keys stored in environment variables, never exposed to browser
  • Server-side caching with TTL to reduce upstream API calls

News Ticker#

  • Pulls from multiple RSS feeds (MassLive Boston, State House News)
  • Displays first 3 items from each feed as <title> - <description>
  • Modular RSS feed configuration for easy addition of new sources

Static Map#

  • Originally Leaflet.js with OpenStreetMap and hardcoded markers
  • Replaced with static image for performance on Raspberry Pi
  • Generated via Snazzy Maps + PowerPoint, served as local webp file
  • Full-width, placed below the card grid

Performance & Optimization#

Memory Constraints (Raspberry Pi 3B+)#

  • Total system memory: 788MB
  • Dockerized Anthias viewer consumes significant resources
  • Strategies employed:
    • Server-side proxy: Eliminates duplicate API calls from browser
    • Lazy loading: Defer non-critical rendering
    • DOM optimization: Remove unused elements, minimize reflows
    • Image optimization: Convert to WebP, use static image over dynamic map
    • Cache management: Server-side cache with periodic clearing
    • Swap avoidance: Swap degrades SD card — keep memory footprint below physical RAM

Font Standardization#

  • Default to Arial for cross-platform consistency
  • Helvetica Neue as preferred fallback
  • Qt WebEngine (Anthias) renders fonts differently than desktop Chrome

Current Configuration#

  • Host: PLT-MBTADisplay (192.168.168.42)
  • Web root: /var/www/MBTADisplay/public
  • Proxy: /opt/mbta-proxy/server.js (Node/Express, port 3000)
  • Process manager: pm2 with systemd service (pm2-administrator)
  • Deployment: Git push → GitHub → manual pull on server
  • Access URLs: http://transit.intra.plgt.com (internal), https://mbtadash.nbkelley.com (Cloudflare)

Historical Notes#

  • Conversation dates: 2026-03-12 to 2026-04-12.
  • Collaborative workflow: Claude AI (creative/prompt engineering) → Claude Code (implementation).
  • Blue Bikes section was added, then fully removed when GBFS feed deprecated.
  • Ferry panel configuration evolved significantly — seasonal routes removed seasonally.
  • Several Claude Code UI hallucinations corrected by user during Bambu Studio discussion.

Sources#

  • ingested/chats/159-Create MBTA Train Dashboard with API.md
  • Claude Code conversation: “MBTADashboard - Prompt Maker” (chat 24)