Home Assistant custom integration with an ODX-derived graphical e-paper designer. Ready projects are dynamic image Media Sources rendered from current Home Assistant data.
Open OpenDisplay Studio in the Home Assistant sidebar to create predefined
or custom displays, edit their logical grids, compose rectangular regions, and
assign Sensor, Calendar, Weather, Hero Weather, Section Title, or Text widgets.
Weather configuration
uses Home Assistant's native entity selector and renders current conditions plus
the selected entity's daily forecast. Project configuration is stored with Home
Assistant's versioned Store; browser localStorage is not used.
Draft projects remain private to the designer. A Ready project is exposed at a stable URI based on its immutable server-generated ID:
media-source://opendisplay_studio/<project-id>
On every resolution the integration deduplicates widget data requirements,
reads current entity states, calendar events, and requested weather forecasts,
renders widget Liquid templates through
trmnl-liquid-py, composes one
TRMNL Framework document, and sends that final HTML to the Renderer. The
Renderer App still knows only HTML, dimensions, and the request-scoped asset
origin allowlist. The designer preview
calls this same Renderer path and shows its PNG, so the visible preview and
final Media Source do not have separate CSS or layout implementations.
Widget templates can use the complete, locally bundled Material Design Icons
catalog through mdi classes. Package-owned files below assets/ are converted
by the integration to bounded base64 data: URIs before HTML reaches the
Renderer. No display render requires remote image or font requests.
Widgets are local-only by default; packages that intentionally need a remote
asset must declare exact allowed origins in their own manifest.
See the widget contract for the schema/data/template boundary, native Home Assistant selectors, and the controlled provider model. See Stage 2 compatibility for the Liquid/TRMNL compatibility baseline retained by Stage 3.
- Click Add the Renderer App repository above and confirm the pre-filled repository URL in Home Assistant.
- Click Open this integration in HACS, download OpenDisplay Studio, and restart Home Assistant when HACS asks you to.
- Click Add OpenDisplay Studio to Home Assistant.
- Confirm Install Renderer. The integration uses Home Assistant Core's
AddonManagerand config-flow progress UI to install, start, discover, and health-check the App.
If a My Home Assistant button is unavailable, use the equivalent manual paths:
- add
https://github.com/Misiu/OpenDisplay-Studio-Appunder Settings > Apps > App store > Repositories; - add this repository to HACS as an Integration;
- open Settings > Devices & services > Add integration and select OpenDisplay Studio.
The integration deliberately does not add the third-party App repository by
itself. Home Assistant Core currently provides AddonManager for a known App,
but no official integration pattern for registering an arbitrary third-party
repository.
See the App-management decision record for the verified Core
APIs, exact Supervisor slug derivation, and the deliberately deferred
system_managed behavior.
Container installations do not have Supervisor App management. The config flow therefore asks for an externally hosted renderer URL and optional bearer token. No LAN port configuration is shown on HA OS/Supervised.
At every config-entry setup, a managed Renderer is checked through
AddonManager. A missing App is scheduled for installation, a stopped App is
scheduled to start, and Home Assistant retries the entry. A running App must
also pass /health with API version 2 and report its pinned TRMNL Framework
version.
The entry stores whether OpenDisplay Studio installed the Renderer. Removing the integration only stops, backs up, and uninstalls a Renderer it created; an independently installed Renderer is left untouched.
python -m pip install -r requirements_test.txt
ruff check .
ruff format --check .
mypy custom_components/opendisplay_studio scripts
pytest
cd frontend-src
npm ci
npm test
npm run buildMIT