An offline-capable, remote-first Plex client built for legacy LG webOS TVs.
Ploff is an unofficial community project and is not affiliated with or endorsed by Plex, Inc.
- Why Ploff
- Architecture at a glance
- Screenshots
- Features
- Requirements
- Installation
- Installation troubleshooting
- First launch
- Compatibility notes
- Security
- Privacy
- Development
- Project structure and documentation
- Contributing
- License
- Built for the TV you already own. Ploff is designed specifically for the Chrome 53 WebView found on legacy LG webOS TVs, with a lightweight interface and no runtime dependencies.
- Works locally without the cloud. Local server discovery and LAN playback require no Plex account. Previously linked Plex Home profiles remain available when Plex cloud services are temporarily unreachable.
- Designed around a remote, not a mouse. Navigation, playback, and search, including optional classic T9 input, support directional remotes and the LG Magic Remote pointer from day one.
- No account required. Point Ploff at a local Plex Media Server and go. Optional Plex linking adds Home profiles, Watchlist, remote servers, Relay failover, and improved multilingual search.
Ploff deliberately keeps the installed TV runtime small and explicit:
LG webOS TV / Chrome 53
|
v
app/index.html + app/styles.css + generated app/app.js
|
+--> feature controllers --> shared TV views / remote + pointer input
|
+--> Plex HTTP client ----------------------> Plex Media Server
|
+--> webOS Luna service -- UDP GDM --------> local Plex discovery
|
+--> Settings / DB8 / bounded local state
app/coordinator/application-controller.js is the composition root: it wires focused
feature controllers together but does not own their Plex requests, DOM, timers, or
private state. Browser runtime code remains dependency-free ES5. app/app.js and
app/styles.css are checked-in generated artifacts for the TV package and must never
be edited directly.
Local Plex discovery and LAN playback do not require Plex cloud services. Plex linking is optional and adds Home profiles, Watchlist, remote servers, Relay failover, and cloud-assisted title aliases. See docs/architecture.md for the full ownership/data-flow model and docs/README.md for the current documentation map.
Click for more screenshots — browse the interface gallery
![]() |
![]() |
| Advanced catalog filters | Search and T9 input |
![]() |
![]() |
| Library recommendations | Series detail and episode navigation |
![]() |
![]() |
| Movie detail and playback choices | Application settings |
Screenshots use a fictional demo library and contain no personal Plex data. All titles, descriptions, and artwork shown are fictional and were created for the demo to avoid using copyrighted media.
- Home, search, libraries, collections, playlists, and Watchlist, all built TV-first
- Optional classic T9 numeric search input, for remotes without a pointer
- Progressive artwork, adjustable card sizes, independent artwork/backdrop download quality, and five selectable visual themes: Simple, Cinema, Premiere, Nova, and Atelier
- Direct Play, Direct Stream, transcoding fallback, and playback diagnostics
- Quality, version, audio, subtitle, synchronization, chapter, and resume controls; Detail keeps Version first and opens an integrated technical browser even when only one file exists
- Contextual Detail media options for season watched/unwatched bulk actions with confirmation and metadata refresh
- Remote-friendly choice dialogs for tracks, playback, and application settings
- Adaptive playback compatibility memory learns from confirmed direct-play failures in Automatic mode, helping Ploff reach a compatible fallback faster.
- Playback progress, watched state, next-episode autoplay, and metadata refresh
- Directional remotes, media keys, LG Magic Remote pointer, and wheel support
- Local server discovery, Plex Home profiles, and automatic LAN/direct/Relay failover
- Fully usable without a Plex account
- Optional per-device configuration backup and restore through a clearly named Plex playlist, with manual or automatic synchronization between Ploff installations
- English, Italian, Spanish, French, German, Brazilian Portuguese, Japanese, and Korean
- Automatic update checks, with a manual Settings check and QR link to the latest GitHub release
- Plex Media Server reachable from the TV
- LG TV with Developer Mode enabled
- Docker (recommended), or Node.js and the LG webOS CLI for manual installation
On the TV, open the Developer Mode app and enable both Dev Mode Status and Key Server before installing Ploff.
This method requires only Docker on the computer. Node.js, the LG webOS CLI, and the Ploff package are contained in the installer image.
-
Install and start Docker.
-
Install the LG Developer Mode app, sign in, and enable Dev Mode Status.
-
Enable Key Server and keep its screen open for the first installation.
-
Run:
docker run --rm -it \ -v ploff-webos-data:/data \ ghcr.io/lucabravi/ploff-webos-installer:latest
-
Enter the TV IP address and the six-character passphrase shown by the Developer Mode app.
The installer retrieves the TV key, builds and verifies the generic IPK, installs Ploff, and launches it.
The ploff-webos-data volume retains only the webOS device configuration and
key. Use the same command for future updates; pairing is skipped while the key
remains valid, and the installer verifies the stored key before every update.
If the Developer Mode session or key expires, renew it on the TV, enable Key
Server, and run the command again to pair automatically.
For automation, prompts can be supplied through PLOFF_TV_IP,
PLOFF_TV_PASSPHRASE, and optionally PLOFF_DEVICE. Run the image with
help, pair, or package instead of the default install command to inspect
the available operations.
Manual installation
Install Node.js and the LG webOS CLI:
npm install -g @webos-tools/cli@3.2.5
ares-setup-device
ares-novacom --getkey --device my-tvKeep Key Server enabled while running ares-novacom. When prompted, enter the
passphrase shown by the Developer Mode app.
Download the IPK and SHA256SUMS from
GitHub Releases, verify the
download, then install and launch it:
shasum -a 256 --check SHA256SUMS # macOS
# sha256sum --check SHA256SUMS # Linux
ares-install --device my-tv io.github.rhapsodos.ploff_<version>_all.ipk
ares-launch --device my-tv io.github.rhapsodos.ploffReplace my-tv with the name configured in ares-setup-device.
Every tagged version publishes a generic IPK, checksum, and multi-architecture Docker installer. Release packages contain no Plex address or credentials.
If installation fails, check the TV-side Developer Mode state before changing Ploff:
- TV cannot be reached: confirm the TV and computer are on the same reachable
network, verify the current TV IP in the Developer Mode app, and make sure Dev
Mode Status is enabled. For a manual CLI setup,
ares-device --system-info --device my-tvis a quick connectivity check. - Pairing /
ares-novacom --getkeyfails: enable Key Server, keep its screen open, and use the current six-character passphrase. With Docker, rerun the installer with thepaircommand; it updates the stored device address and retrieves a fresh key. - A previously working install asks to pair again: the Developer Mode session/key may have expired or the TV IP may have changed. Renew Developer Mode on the TV, enable Key Server, then pair again. The persistent Docker volume can be reused.
ares-installor launch fails after a long idle period: first verify the Developer Mode session and device connection. Re-pair before rebuilding the package; packaging does not repair an expired TV key.- Non-interactive Docker use fails before pairing: provide
PLOFF_TV_IPandPLOFF_TV_PASSPHRASE; optionally setPLOFF_DEVICEwhen maintaining more than one configured TV.
For manual installations, ares-setup-device --listfull shows the configured device
record. Do not place TV passphrases, private keys, Plex tokens, or personal server
addresses in issues, logs, or repository files.
No Plex address or token is embedded in Ploff. On first launch, the app finds
local servers and can work without a Plex account. Linking at plex.tv/link
adds Plex Home profiles, remote servers, Watchlist, remote/Relay failover, and
improved multilingual search through localized titles and aliases. Search
results are still limited to media available on the active server. Servers can
always be entered or changed manually in Settings.
Previously linked profiles and local playback remain available if Plex cloud services are offline. Search also remains local; online title aliases are shown only after matching media is confirmed on the active server.
Codec support depends on the TV and Plex Media Server; unsupported media can be transcoded by Plex. Applications installed through LG Developer Mode remain subject to the Developer Mode session and package expiration rules. Linking a Plex account requires internet initially, while previously cached profiles and local playback remain available offline.
- Plex account tokens and cached Plex Home profiles are stored in a private,
app-owned webOS DB8 kind. They are never written to browser
localStorageby the packaged TV app. - If private DB8 storage is unavailable, credentials remain in memory for the current session only.
- Generated IPK files never contain a Plex address or credentials.
- Local HTTP connections remain supported for older TVs, but an untrusted LAN could observe metadata and authenticated media URLs. Prefer Plex HTTPS endpoints on shared networks, and treat the TV and home LAN as trusted devices.
See SECURITY.md for the full threat model and private reporting instructions, and PRIVACY.md for the data-handling policy.
npm ci
npm run build:styles
npm run build:app
./scripts/package-tv-shell.sh
./scripts/install-webos.sh my-tvinstall-webos.sh builds, installs, and launches the app. Generated packages
always use neutral defaults and exclude app/config.local.js.
Application coordination is maintained as complete responsibility-based UMD
modules in app/coordinator/, with focused support modules under app/;
app/app.js is the generated ES5 bundle shipped to the TV. The legacy
app/source/ directory must not be reintroduced.
Node.js 20 or newer is required only for development and tests, not when using the Docker installer.
npm ci
npm run verifynpm run verify checks that the generated application bundle is current, then runs:
- ESLint
- JavaScript type-checking
- The complete test suite
- Chrome 53 compatibility checks
- Publishable repository hygiene checks
Before a release, or after changing asynchronous lifecycle and teardown code, run the extended gate:
npm run test:pre-releaseIt runs the complete verification suite followed by the forced-GC memory lifecycle
stress test documented in docs/testing.md. To build a local release artifact after metadata and
physical signoff are ready, use npm run release:package; it rebuilds generated assets, runs the
pre-release gate, packages and inspects the IPK, and writes dist/SHA256SUMS without changing Git
or the application version.
./scripts/preview-local.shThe script serves the project on http://127.0.0.1:8098/app/ and opens the
browser when supported. Pass a different port as its first argument, for example
./scripts/preview-local.sh 9000. Browser preview cannot perform webOS multicast
discovery, but a server can be entered manually and is retained in local
storage.
To stage and open the app in the macOS webOS TV Simulator, use:
./scripts/install-simulator.shThe script rebuilds the generated assets, imports the app through the simulator's
virtual remote, and leaves the physical TV untouched. Use --stage-only to only
prepare the import directory.
- docs/README.md — authoritative current-document index
- docs/architecture.md — runtime components and design rationale
- docs/features.md — current viewer-facing capabilities
- docs/themes.md — visual-theme architecture, isolation rules, and extension workflow
- docs/settings.md — persisted Settings schema, migrations, and extension workflow
- docs/diagnostics.md — privacy-safe support reports and diagnostics export workflow
- docs/playback-invariants.md — TV-verified seek and resume behavior
- docs/testing.md — release test matrix
- CHANGELOG.md — release history
- CONTRIBUTING.md — contribution requirements
Bug reports and pull requests are welcome. Please read
CONTRIBUTING.md for the coding style, testing, and verification
requirements (npm run verify) applied to every change.
Released under the MIT License.
Plex and Plex Media Server are trademarks of Plex, Inc. Ploff is independently developed and is not endorsed by Plex, Inc.






